]>
Commit | Line | Data |
---|---|---|
b84d2592 DM |
1 | /// Configure OpenId realms |
2 | ||
3 | use anyhow::{bail, Error}; | |
4 | use serde_json::Value; | |
5 | use ::serde::{Deserialize, Serialize}; | |
6 | ||
7 | use proxmox::api::{api, Permission, Router, RpcEnvironment}; | |
8 | ||
8cc3760e DM |
9 | use pbs_api_types::{ |
10 | PROXMOX_CONFIG_DIGEST_SCHEMA, REALM_ID_SCHEMA, PRIV_SYS_AUDIT, PRIV_REALM_ALLOCATE, | |
11 | }; | |
21211748 | 12 | use pbs_config::domains::{self, OpenIdRealmConfig, OpenIdRealmConfigUpdater}; |
b84d2592 DM |
13 | |
14 | #[api( | |
15 | input: { | |
16 | properties: {}, | |
17 | }, | |
18 | returns: { | |
19 | description: "List of configured OpenId realms.", | |
20 | type: Array, | |
21 | items: { type: OpenIdRealmConfig }, | |
22 | }, | |
23 | access: { | |
bbd34d70 | 24 | permission: &Permission::Privilege(&["access", "domains"], PRIV_REALM_ALLOCATE, false), |
b84d2592 DM |
25 | }, |
26 | )] | |
27 | /// List configured OpenId realms | |
28 | pub fn list_openid_realms( | |
29 | _param: Value, | |
30 | mut rpcenv: &mut dyn RpcEnvironment, | |
31 | ) -> Result<Vec<OpenIdRealmConfig>, Error> { | |
32 | ||
33 | let (config, digest) = domains::config()?; | |
34 | ||
35 | let list = config.convert_to_typed_array("openid")?; | |
36 | ||
37 | rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into(); | |
38 | ||
39 | Ok(list) | |
40 | } | |
41 | ||
42 | #[api( | |
43 | protected: true, | |
44 | input: { | |
45 | properties: { | |
46 | config: { | |
47 | type: OpenIdRealmConfig, | |
48 | flatten: true, | |
49 | }, | |
50 | }, | |
51 | }, | |
52 | access: { | |
bbd34d70 | 53 | permission: &Permission::Privilege(&["access", "domains"], PRIV_REALM_ALLOCATE, false), |
b84d2592 DM |
54 | }, |
55 | )] | |
56 | /// Create a new OpenId realm | |
57 | pub fn create_openid_realm(config: OpenIdRealmConfig) -> Result<(), Error> { | |
58 | ||
59 | let _lock = domains::lock_config()?; | |
60 | ||
61 | let (mut domains, _digest) = domains::config()?; | |
62 | ||
63 | if config.realm == "pbs" || | |
64 | config.realm == "pam" || | |
65 | domains.sections.get(&config.realm).is_some() | |
66 | { | |
67 | bail!("realm '{}' already exists.", config.realm); | |
68 | } | |
69 | ||
70 | domains.set_data(&config.realm, "openid", &config)?; | |
71 | ||
72 | domains::save_config(&domains)?; | |
73 | ||
74 | Ok(()) | |
75 | } | |
76 | ||
77 | #[api( | |
78 | protected: true, | |
79 | input: { | |
80 | properties: { | |
81 | realm: { | |
82 | schema: REALM_ID_SCHEMA, | |
83 | }, | |
84 | digest: { | |
85 | optional: true, | |
86 | schema: PROXMOX_CONFIG_DIGEST_SCHEMA, | |
87 | }, | |
88 | }, | |
89 | }, | |
90 | access: { | |
bbd34d70 | 91 | permission: &Permission::Privilege(&["access", "domains"], PRIV_REALM_ALLOCATE, false), |
b84d2592 DM |
92 | }, |
93 | )] | |
94 | /// Remove a OpenID realm configuration | |
95 | pub fn delete_openid_realm( | |
96 | realm: String, | |
97 | digest: Option<String>, | |
98 | _rpcenv: &mut dyn RpcEnvironment, | |
99 | ) -> Result<(), Error> { | |
100 | ||
101 | let _lock = domains::lock_config()?; | |
102 | ||
103 | let (mut domains, expected_digest) = domains::config()?; | |
104 | ||
105 | if let Some(ref digest) = digest { | |
106 | let digest = proxmox::tools::hex_to_digest(digest)?; | |
107 | crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?; | |
108 | } | |
109 | ||
110 | if domains.sections.remove(&realm).is_none() { | |
111 | bail!("realm '{}' does not exist.", realm); | |
112 | } | |
113 | ||
114 | domains::save_config(&domains)?; | |
115 | ||
116 | Ok(()) | |
117 | } | |
118 | ||
119 | #[api( | |
120 | input: { | |
121 | properties: { | |
122 | realm: { | |
123 | schema: REALM_ID_SCHEMA, | |
124 | }, | |
125 | }, | |
126 | }, | |
127 | returns: { type: OpenIdRealmConfig }, | |
128 | access: { | |
129 | permission: &Permission::Privilege(&["access", "domains"], PRIV_SYS_AUDIT, false), | |
130 | }, | |
131 | )] | |
132 | /// Read the OpenID realm configuration | |
133 | pub fn read_openid_realm( | |
134 | realm: String, | |
135 | mut rpcenv: &mut dyn RpcEnvironment, | |
136 | ) -> Result<OpenIdRealmConfig, Error> { | |
137 | ||
138 | let (domains, digest) = domains::config()?; | |
139 | ||
140 | let config = domains.lookup("openid", &realm)?; | |
141 | ||
142 | rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into(); | |
143 | ||
144 | Ok(config) | |
145 | } | |
146 | ||
147 | #[api()] | |
148 | #[derive(Serialize, Deserialize)] | |
149 | #[serde(rename_all="kebab-case")] | |
150 | #[allow(non_camel_case_types)] | |
151 | /// Deletable property name | |
152 | pub enum DeletableProperty { | |
153 | /// Delete the client key. | |
154 | client_key, | |
155 | /// Delete the comment property. | |
156 | comment, | |
3b7b1dfb DM |
157 | /// Delete the autocreate property |
158 | autocreate, | |
b84d2592 DM |
159 | } |
160 | ||
161 | #[api( | |
162 | protected: true, | |
163 | input: { | |
164 | properties: { | |
165 | realm: { | |
166 | schema: REALM_ID_SCHEMA, | |
167 | }, | |
e4a5c072 DM |
168 | update: { |
169 | type: OpenIdRealmConfigUpdater, | |
170 | flatten: true, | |
b84d2592 DM |
171 | }, |
172 | delete: { | |
173 | description: "List of properties to delete.", | |
174 | type: Array, | |
175 | optional: true, | |
176 | items: { | |
177 | type: DeletableProperty, | |
178 | } | |
179 | }, | |
180 | digest: { | |
181 | optional: true, | |
182 | schema: PROXMOX_CONFIG_DIGEST_SCHEMA, | |
183 | }, | |
184 | }, | |
185 | }, | |
186 | returns: { type: OpenIdRealmConfig }, | |
187 | access: { | |
bbd34d70 | 188 | permission: &Permission::Privilege(&["access", "domains"], PRIV_REALM_ALLOCATE, false), |
b84d2592 DM |
189 | }, |
190 | )] | |
191 | /// Update an OpenID realm configuration | |
192 | pub fn update_openid_realm( | |
193 | realm: String, | |
e4a5c072 | 194 | update: OpenIdRealmConfigUpdater, |
b84d2592 DM |
195 | delete: Option<Vec<DeletableProperty>>, |
196 | digest: Option<String>, | |
197 | _rpcenv: &mut dyn RpcEnvironment, | |
198 | ) -> Result<(), Error> { | |
199 | ||
200 | let _lock = domains::lock_config()?; | |
201 | ||
202 | let (mut domains, expected_digest) = domains::config()?; | |
203 | ||
204 | if let Some(ref digest) = digest { | |
205 | let digest = proxmox::tools::hex_to_digest(digest)?; | |
206 | crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?; | |
207 | } | |
208 | ||
209 | let mut config: OpenIdRealmConfig = domains.lookup("openid", &realm)?; | |
210 | ||
211 | if let Some(delete) = delete { | |
212 | for delete_prop in delete { | |
213 | match delete_prop { | |
214 | DeletableProperty::client_key => { config.client_key = None; }, | |
215 | DeletableProperty::comment => { config.comment = None; }, | |
3b7b1dfb | 216 | DeletableProperty::autocreate => { config.autocreate = None; }, |
b84d2592 DM |
217 | } |
218 | } | |
219 | } | |
220 | ||
e4a5c072 | 221 | if let Some(comment) = update.comment { |
b84d2592 DM |
222 | let comment = comment.trim().to_string(); |
223 | if comment.is_empty() { | |
224 | config.comment = None; | |
225 | } else { | |
226 | config.comment = Some(comment); | |
227 | } | |
228 | } | |
229 | ||
e4a5c072 DM |
230 | if let Some(issuer_url) = update.issuer_url { config.issuer_url = issuer_url; } |
231 | if let Some(client_id) = update.client_id { config.client_id = client_id; } | |
b84d2592 | 232 | |
e4a5c072 DM |
233 | if update.client_key.is_some() { config.client_key = update.client_key; } |
234 | if update.autocreate.is_some() { config.autocreate = update.autocreate; } | |
b84d2592 DM |
235 | |
236 | domains.set_data(&realm, "openid", &config)?; | |
237 | ||
238 | domains::save_config(&domains)?; | |
239 | ||
240 | Ok(()) | |
241 | } | |
242 | ||
243 | const ITEM_ROUTER: Router = Router::new() | |
244 | .get(&API_METHOD_READ_OPENID_REALM) | |
245 | .put(&API_METHOD_UPDATE_OPENID_REALM) | |
246 | .delete(&API_METHOD_DELETE_OPENID_REALM); | |
247 | ||
248 | pub const ROUTER: Router = Router::new() | |
249 | .get(&API_METHOD_LIST_OPENID_REALMS) | |
250 | .post(&API_METHOD_CREATE_OPENID_REALM) | |
9779ad0b | 251 | .match_all("realm", &ITEM_ROUTER); |