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}