Skip to main content

openstack_keystone_core/token/backend/fernet/
trust.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
15use rmp::{decode::read_pfix, encode::write_pfix};
16use std::io::Write;
17
18use crate::token::{
19    backend::fernet::{FernetTokenProvider, MsgPackToken, utils},
20    error::TokenProviderError,
21    types::TrustPayload,
22};
23
24impl MsgPackToken for TrustPayload {
25    type Token = Self;
26
27    fn assemble<W: Write>(
28        &self,
29        wd: &mut W,
30        fernet_provider: &FernetTokenProvider,
31    ) -> Result<(), TokenProviderError> {
32        utils::write_uuid(wd, &self.user_id)?;
33        write_pfix(
34            wd,
35            fernet_provider.encode_auth_methods(self.methods.clone())?,
36        )
37        .map_err(|x| TokenProviderError::RmpEncode(x.to_string()))?;
38        utils::write_uuid(wd, &self.project_id)?;
39        utils::write_time(wd, self.expires_at)?;
40        utils::write_audit_ids(wd, self.audit_ids.clone())?;
41        utils::write_uuid(wd, &self.trust_id)?;
42
43        Ok(())
44    }
45
46    fn disassemble(
47        rd: &mut &[u8],
48        fernet_provider: &FernetTokenProvider,
49    ) -> Result<Self::Token, TokenProviderError> {
50        // Order of reading is important
51        let user_id = utils::read_uuid(rd)?;
52        let methods: Vec<String> = fernet_provider
53            .decode_auth_methods(read_pfix(rd)?)?
54            .into_iter()
55            .collect();
56        let project_id = utils::read_uuid(rd)?;
57        let expires_at = utils::read_time(rd)?;
58        let audit_ids: Vec<String> = utils::read_audit_ids(rd)?.into_iter().collect();
59        let trust_id = utils::read_uuid(rd)?;
60
61        Ok(Self {
62            user_id,
63            methods,
64            expires_at,
65            audit_ids,
66            project_id,
67            trust_id,
68            ..Default::default()
69        })
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use chrono::{Local, SubsecRound};
76    use uuid::Uuid;
77
78    use super::*;
79    use crate::token::tests::setup_config;
80
81    #[test]
82    fn test_roundtrip() {
83        let token = TrustPayload {
84            user_id: Uuid::new_v4().simple().to_string(),
85            methods: vec!["password".into()],
86            project_id: Uuid::new_v4().simple().to_string(),
87            trust_id: Uuid::new_v4().simple().to_string(),
88            audit_ids: vec!["Zm9vCg".into()],
89            expires_at: Local::now().trunc_subsecs(0).into(),
90            ..Default::default()
91        };
92
93        let provider = FernetTokenProvider::new(setup_config());
94
95        let mut buf = vec![];
96        token.assemble(&mut buf, &provider).unwrap();
97        let encoded_buf = buf.clone();
98        let decoded = TrustPayload::disassemble(&mut encoded_buf.as_slice(), &provider).unwrap();
99        assert_eq!(token, decoded);
100    }
101}