openstack_keystone_core/trust/mod.rs
1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// SPDX-License-Identifier: Apache-2.0
14//! # Trust provider.
15//!
16//! Trusts.
17//!
18//! A trust represents a user's (the trustor) authorization to delegate roles to
19//! another user (the trustee), and optionally allow the trustee to impersonate
20//! the trustor. After the trustor has created a trust, the trustee can specify
21//! the trust's id attribute as part of an authentication request to then create
22//! a token representing the delegated authority of the trustor.
23//!
24//! The trust contains constraints on the delegated attributes. A token created
25//! based on a trust will convey a subset of the trustor's roles on the
26//! specified project. Optionally, the trust may only be valid for a specified
27//! time period, as defined by expires_at. If no expires_at is specified, then
28//! the trust is valid until it is explicitly revoked.
29//!
30//! The impersonation flag allows the trustor to optionally delegate
31//! impersonation abilities to the trustee. To services validating the token,
32//! the trustee will appear as the trustor, although the token will also contain
33//! the impersonation flag to indicate that this behavior is in effect.
34//!
35//! A project_id may not be specified without at least one role, and vice versa.
36//! In other words, there is no way of implicitly delegating all roles to a
37//! trustee, in order to prevent users accidentally creating trust that are much
38//! more broad in scope than intended. A trust without a project_id or any
39//! delegated roles is unscoped, and therefore does not represent authorization
40//! on a specific resource.
41//!
42//! Trusts are immutable. If the trustee or trustor wishes to modify the
43//! attributes of the trust, they should create a new trust and delete the old
44//! trust. If a trust is deleted, any tokens generated based on the trust are
45//! immediately revoked.
46//!
47//! If the trustor loses access to any delegated attributes, the trust becomes
48//! immediately invalid and any tokens generated based on the trust are
49//! immediately revoked.
50//!
51//! Trusts can also be chained, meaning, a trust can be created by using a trust
52//! scoped token.
53
54use async_trait::async_trait;
55
56pub mod api;
57pub mod backend;
58pub mod error;
59#[cfg(any(test, feature = "mock"))]
60mod mock;
61pub mod service;
62pub mod types;
63
64use crate::config::Config;
65use crate::keystone::ServiceState;
66use crate::plugin_manager::PluginManagerApi;
67use crate::trust::service::TrustService;
68
69pub use error::TrustProviderError;
70#[cfg(any(test, feature = "mock"))]
71pub use mock::MockTrustProvider;
72pub use types::*;
73
74/// Trust provider.
75pub enum TrustProvider {
76 Service(TrustService),
77 #[cfg(any(test, feature = "mock"))]
78 Mock(MockTrustProvider),
79}
80
81impl TrustProvider {
82 pub fn new<P: PluginManagerApi>(
83 config: &Config,
84 plugin_manager: &P,
85 ) -> Result<Self, TrustProviderError> {
86 Ok(Self::Service(TrustService::new(config, plugin_manager)?))
87 }
88}
89
90#[async_trait]
91impl TrustApi for TrustProvider {
92 /// Get trust by ID.
93 async fn get_trust<'a>(
94 &self,
95 state: &ServiceState,
96 id: &'a str,
97 ) -> Result<Option<Trust>, TrustProviderError> {
98 match self {
99 Self::Service(provider) => provider.get_trust(state, id).await,
100 #[cfg(any(test, feature = "mock"))]
101 Self::Mock(provider) => provider.get_trust(state, id).await,
102 }
103 }
104
105 /// Resolve trust delegation chain by the trust ID.
106 async fn get_trust_delegation_chain<'a>(
107 &self,
108 state: &ServiceState,
109 id: &'a str,
110 ) -> Result<Option<Vec<Trust>>, TrustProviderError> {
111 match self {
112 Self::Service(provider) => provider.get_trust_delegation_chain(state, id).await,
113 #[cfg(any(test, feature = "mock"))]
114 Self::Mock(provider) => provider.get_trust_delegation_chain(state, id).await,
115 }
116 }
117
118 /// List trusts.
119 async fn list_trusts(
120 &self,
121 state: &ServiceState,
122 params: &TrustListParameters,
123 ) -> Result<Vec<Trust>, TrustProviderError> {
124 match self {
125 Self::Service(provider) => provider.list_trusts(state, params).await,
126 #[cfg(any(test, feature = "mock"))]
127 Self::Mock(provider) => provider.list_trusts(state, params).await,
128 }
129 }
130
131 /// Validate trust delegation chain.
132 ///
133 /// - redelegation deepness cannot exceed the global limit.
134 /// - redelegated trusts must not specify use limit.
135 /// - validate redelegated trust expiration is not later than of the
136 /// original.
137 /// - redelegated trust must not add new roles.
138 async fn validate_trust_delegation_chain(
139 &self,
140 state: &ServiceState,
141 trust: &Trust,
142 ) -> Result<bool, TrustProviderError> {
143 match self {
144 Self::Service(provider) => provider.validate_trust_delegation_chain(state, trust).await,
145 #[cfg(any(test, feature = "mock"))]
146 Self::Mock(provider) => provider.validate_trust_delegation_chain(state, trust).await,
147 }
148 }
149}