]>
Commit | Line | Data |
---|---|---|
a670b99d WB |
1 | //! For now this only has the TFA subdir, which is in this file. |
2 | //! If we add more, it should be moved into a sub module. | |
3 | ||
e6e2927e | 4 | use anyhow::{format_err, Error}; |
25877d05 | 5 | use hex::FromHex; |
e6e2927e | 6 | use serde::{Deserialize, Serialize}; |
a670b99d | 7 | |
6ef1b649 | 8 | use proxmox_router::list_subdirs_api_method; |
e6e2927e WB |
9 | use proxmox_router::{Permission, Router, RpcEnvironment, SubdirMap}; |
10 | use proxmox_schema::api; | |
a670b99d | 11 | |
6227654a DM |
12 | use pbs_api_types::PROXMOX_CONFIG_DIGEST_SCHEMA; |
13 | ||
a670b99d WB |
14 | use crate::config::tfa::{self, WebauthnConfig, WebauthnConfigUpdater}; |
15 | ||
16 | pub const ROUTER: Router = Router::new() | |
17 | .get(&list_subdirs_api_method!(SUBDIRS)) | |
18 | .subdirs(SUBDIRS); | |
19 | ||
20 | const SUBDIRS: SubdirMap = &[("webauthn", &WEBAUTHN_ROUTER)]; | |
21 | ||
22 | const WEBAUTHN_ROUTER: Router = Router::new() | |
23 | .get(&API_METHOD_GET_WEBAUTHN_CONFIG) | |
24 | .put(&API_METHOD_UPDATE_WEBAUTHN_CONFIG); | |
25 | ||
26 | #[api( | |
27 | protected: true, | |
28 | input: { | |
29 | properties: {}, | |
30 | }, | |
31 | returns: { | |
32 | type: WebauthnConfig, | |
33 | optional: true, | |
34 | }, | |
35 | access: { | |
36 | permission: &Permission::Anybody, | |
37 | }, | |
38 | )] | |
39 | /// Get the TFA configuration. | |
40 | pub fn get_webauthn_config( | |
41 | mut rpcenv: &mut dyn RpcEnvironment, | |
42 | ) -> Result<Option<WebauthnConfig>, Error> { | |
43 | let (config, digest) = match tfa::webauthn_config()? { | |
44 | Some(c) => c, | |
45 | None => return Ok(None), | |
46 | }; | |
25877d05 | 47 | rpcenv["digest"] = hex::encode(&digest).into(); |
a670b99d WB |
48 | Ok(Some(config)) |
49 | } | |
50 | ||
e6e2927e WB |
51 | #[api()] |
52 | #[derive(Serialize, Deserialize)] | |
53 | #[serde(rename_all = "kebab-case")] | |
54 | /// Deletable property name | |
55 | pub enum DeletableProperty { | |
56 | /// Delete the origin property. | |
57 | Origin, | |
58 | } | |
59 | ||
a670b99d WB |
60 | #[api( |
61 | protected: true, | |
62 | input: { | |
63 | properties: { | |
64 | webauthn: { | |
65 | flatten: true, | |
66 | type: WebauthnConfigUpdater, | |
67 | }, | |
e6e2927e WB |
68 | delete: { |
69 | description: "List of properties to delete.", | |
70 | type: Array, | |
71 | optional: true, | |
72 | items: { | |
73 | type: DeletableProperty, | |
74 | } | |
75 | }, | |
a670b99d WB |
76 | digest: { |
77 | optional: true, | |
78 | schema: PROXMOX_CONFIG_DIGEST_SCHEMA, | |
79 | }, | |
80 | }, | |
81 | }, | |
82 | )] | |
83 | /// Update the TFA configuration. | |
84 | pub fn update_webauthn_config( | |
85 | webauthn: WebauthnConfigUpdater, | |
e6e2927e | 86 | delete: Option<Vec<DeletableProperty>>, |
a670b99d WB |
87 | digest: Option<String>, |
88 | ) -> Result<(), Error> { | |
89 | let _lock = tfa::write_lock(); | |
90 | ||
91 | let mut tfa = tfa::read()?; | |
92 | ||
93 | if let Some(wa) = &mut tfa.webauthn { | |
94 | if let Some(ref digest) = digest { | |
25877d05 | 95 | let digest = <[u8; 32]>::from_hex(digest)?; |
9407810f WB |
96 | crate::tools::detect_modified_configuration_file( |
97 | &digest, | |
9a37bd6c | 98 | &crate::config::tfa::webauthn_config_digest(wa)?, |
9407810f | 99 | )?; |
a670b99d | 100 | } |
e6e2927e WB |
101 | |
102 | if let Some(delete) = delete { | |
103 | for delete in delete { | |
104 | match delete { | |
105 | DeletableProperty::Origin => { | |
106 | wa.origin = None; | |
107 | } | |
108 | } | |
109 | } | |
110 | } | |
111 | ||
112 | if let Some(rp) = webauthn.rp { | |
113 | wa.rp = rp; | |
114 | } | |
115 | if webauthn.origin.is_some() { | |
116 | wa.origin = webauthn.origin; | |
117 | } | |
118 | if let Some(id) = webauthn.id { | |
119 | wa.id = id; | |
120 | } | |
a670b99d | 121 | } else { |
e6e2927e WB |
122 | let rp = webauthn |
123 | .rp | |
124 | .ok_or_else(|| format_err!("missing proeprty: 'rp'"))?; | |
125 | let origin = webauthn.origin; | |
126 | let id = webauthn | |
127 | .id | |
128 | .ok_or_else(|| format_err!("missing property: 'id'"))?; | |
a8a20e92 | 129 | tfa.webauthn = Some(WebauthnConfig { rp, origin, id }); |
a670b99d WB |
130 | } |
131 | ||
132 | tfa::write(&tfa)?; | |
133 | ||
134 | Ok(()) | |
135 | } |