Skip to main content

openstack_keystone_core/revoke/
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//! # Token revocation provider.
15//!
16//! Token revocation may be implemented in different ways, but in most cases
17//! would be represented by the presence of the revocation or the invalidation
18//! record matching the certain token parameters.
19//!
20//! Default backend is the [`sql`](crate::revoke::backend::sql) and uses the
21//! database [table](crate::db::entity::revocation_event::Model) for storing the
22//! revocation events. They have their own expiration.
23//!
24//! Tokens are not invalidated by saving the exact value, but rather by saving
25//! certain attributes of the token.
26//!
27//! Following attributes are used for matching of the regular fernet token:
28//!
29//!   - `audit_id`
30//!   - `domain_id`
31//!   - `expires_at`
32//!   - `project_id`
33//!   - `user_id`
34//!
35//! Additionally the `token.issued_at` is compared to be lower than the
36//! `issued_before` field of the revocation record.
37
38use async_trait::async_trait;
39
40pub mod backend;
41pub mod error;
42#[cfg(any(test, feature = "mock"))]
43mod mock;
44pub mod service;
45pub mod types;
46
47use crate::config::Config;
48use crate::keystone::ServiceState;
49use crate::plugin_manager::PluginManagerApi;
50use crate::revoke::service::RevokeService;
51use crate::token::types::Token;
52
53pub use error::RevokeProviderError;
54#[cfg(any(test, feature = "mock"))]
55pub use mock::MockRevokeProvider;
56pub use types::*;
57
58/// Revoke provider.
59pub enum RevokeProvider {
60    Service(RevokeService),
61    #[cfg(any(test, feature = "mock"))]
62    Mock(MockRevokeProvider),
63}
64
65impl RevokeProvider {
66    pub fn new<P: PluginManagerApi>(
67        config: &Config,
68        plugin_manager: &P,
69    ) -> Result<Self, RevokeProviderError> {
70        Ok(Self::Service(RevokeService::new(config, plugin_manager)?))
71    }
72}
73
74#[async_trait]
75impl RevokeApi for RevokeProvider {
76    /// Create revocation event.
77    async fn create_revocation_event(
78        &self,
79        state: &ServiceState,
80        event: RevocationEventCreate,
81    ) -> Result<RevocationEvent, RevokeProviderError> {
82        match self {
83            Self::Service(provider) => provider.create_revocation_event(state, event).await,
84            #[cfg(any(test, feature = "mock"))]
85            Self::Mock(provider) => provider.create_revocation_event(state, event).await,
86        }
87    }
88
89    /// Check whether the token has been revoked or not.
90    ///
91    /// Checks revocation events matching the token parameters and return
92    /// `false` if their count is more than `0`.
93    async fn is_token_revoked(
94        &self,
95        state: &ServiceState,
96        token: &Token,
97    ) -> Result<bool, RevokeProviderError> {
98        match self {
99            Self::Service(provider) => provider.is_token_revoked(state, token).await,
100            #[cfg(any(test, feature = "mock"))]
101            Self::Mock(provider) => provider.is_token_revoked(state, token).await,
102        }
103    }
104
105    /// Revoke the token.
106    ///
107    /// Mark the token as revoked to prohibit from being used even while not
108    /// expired.
109    async fn revoke_token(
110        &self,
111        state: &ServiceState,
112        token: &Token,
113    ) -> Result<(), RevokeProviderError> {
114        match self {
115            Self::Service(provider) => provider.revoke_token(state, token).await,
116            #[cfg(any(test, feature = "mock"))]
117            Self::Mock(provider) => provider.revoke_token(state, token).await,
118        }
119    }
120}