]> git.proxmox.com Git - proxmox-backup.git/blame - src/api2/config/access/tfa.rs
tree-wide: fix needless borrows
[proxmox-backup.git] / src / api2 / config / access / tfa.rs
CommitLineData
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 4use anyhow::{format_err, Error};
25877d05 5use hex::FromHex;
e6e2927e 6use serde::{Deserialize, Serialize};
a670b99d 7
6ef1b649 8use proxmox_router::list_subdirs_api_method;
e6e2927e
WB
9use proxmox_router::{Permission, Router, RpcEnvironment, SubdirMap};
10use proxmox_schema::api;
a670b99d 11
6227654a
DM
12use pbs_api_types::PROXMOX_CONFIG_DIGEST_SCHEMA;
13
a670b99d
WB
14use crate::config::tfa::{self, WebauthnConfig, WebauthnConfigUpdater};
15
16pub const ROUTER: Router = Router::new()
17 .get(&list_subdirs_api_method!(SUBDIRS))
18 .subdirs(SUBDIRS);
19
20const SUBDIRS: SubdirMap = &[("webauthn", &WEBAUTHN_ROUTER)];
21
22const 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.
40pub 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
55pub 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.
84pub 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}