diff --git a/pbs-api-types/src/lib.rs b/pbs-api-types/src/lib.rs index 01c14cc4..4247bba3 100644 --- a/pbs-api-types/src/lib.rs +++ b/pbs-api-types/src/lib.rs @@ -68,6 +68,9 @@ pub use crypto::{CryptMode, Fingerprint, bytes_as_fingerprint}; pub mod file_restore; +mod openid; +pub use openid::*; + mod remote; pub use remote::*; diff --git a/pbs-api-types/src/openid.rs b/pbs-api-types/src/openid.rs new file mode 100644 index 00000000..65967bd1 --- /dev/null +++ b/pbs-api-types/src/openid.rs @@ -0,0 +1,121 @@ +use serde::{Deserialize, Serialize}; + +use proxmox_schema::{ + api, ApiStringFormat, ArraySchema, Schema, StringSchema, Updater, +}; + +use super::{ + PROXMOX_SAFE_ID_REGEX, PROXMOX_SAFE_ID_FORMAT, REALM_ID_SCHEMA, + SINGLE_LINE_COMMENT_SCHEMA, +}; + +pub const OPENID_SCOPE_FORMAT: ApiStringFormat = + ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX); + +pub const OPENID_SCOPE_SCHEMA: Schema = StringSchema::new("OpenID Scope Name.") + .format(&OPENID_SCOPE_FORMAT) + .schema(); + +pub const OPENID_SCOPE_ARRAY_SCHEMA: Schema = ArraySchema::new( + "Array of OpenId Scopes.", &OPENID_SCOPE_SCHEMA).schema(); + +pub const OPENID_SCOPE_LIST_FORMAT: ApiStringFormat = + ApiStringFormat::PropertyString(&OPENID_SCOPE_ARRAY_SCHEMA); + +pub const OPENID_DEFAILT_SCOPE_LIST: &'static str = "email profile"; +pub const OPENID_SCOPE_LIST_SCHEMA: Schema = StringSchema::new("OpenID Scope List") + .format(&OPENID_SCOPE_LIST_FORMAT) + .default(OPENID_DEFAILT_SCOPE_LIST) + .schema(); + +pub const OPENID_ACR_FORMAT: ApiStringFormat = + ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX); + +pub const OPENID_ACR_SCHEMA: Schema = StringSchema::new("OpenID Authentication Context Class Reference.") + .format(&OPENID_SCOPE_FORMAT) + .schema(); + +pub const OPENID_ACR_ARRAY_SCHEMA: Schema = ArraySchema::new( + "Array of OpenId ACRs.", &OPENID_ACR_SCHEMA).schema(); + +pub const OPENID_ACR_LIST_FORMAT: ApiStringFormat = + ApiStringFormat::PropertyString(&OPENID_ACR_ARRAY_SCHEMA); + +pub const OPENID_ACR_LIST_SCHEMA: Schema = StringSchema::new("OpenID ACR List") + .format(&OPENID_ACR_LIST_FORMAT) + .schema(); + +pub const OPENID_USERNAME_CLAIM_SCHEMA: Schema = StringSchema::new( + "Use the value of this attribute/claim as unique user name. It \ + is up to the identity provider to guarantee the uniqueness. The \ + OpenID specification only guarantees that Subject ('sub') is \ + unique. Also make sure that the user is not allowed to change that \ + attribute by himself!") + .max_length(64) + .min_length(1) + .format(&PROXMOX_SAFE_ID_FORMAT) .schema(); + +#[api( + properties: { + realm: { + schema: REALM_ID_SCHEMA, + }, + "client-key": { + optional: true, + }, + "scopes": { + schema: OPENID_SCOPE_LIST_SCHEMA, + optional: true, + }, + "acr-values": { + schema: OPENID_ACR_LIST_SCHEMA, + optional: true, + }, + prompt: { + description: "OpenID Prompt", + type: String, + format: &PROXMOX_SAFE_ID_FORMAT, + optional: true, + }, + comment: { + optional: true, + schema: SINGLE_LINE_COMMENT_SCHEMA, + }, + autocreate: { + optional: true, + default: false, + }, + "username-claim": { + schema: OPENID_USERNAME_CLAIM_SCHEMA, + optional: true, + }, + }, +)] +#[derive(Serialize, Deserialize, Updater)] +#[serde(rename_all="kebab-case")] +/// OpenID configuration properties. +pub struct OpenIdRealmConfig { + #[updater(skip)] + pub realm: String, + /// OpenID Issuer Url + pub issuer_url: String, + /// OpenID Client ID + pub client_id: String, + #[serde(skip_serializing_if="Option::is_none")] + pub scopes: Option, + #[serde(skip_serializing_if="Option::is_none")] + pub acr_values: Option, + #[serde(skip_serializing_if="Option::is_none")] + pub prompt: Option, + /// OpenID Client Key + #[serde(skip_serializing_if="Option::is_none")] + pub client_key: Option, + #[serde(skip_serializing_if="Option::is_none")] + pub comment: Option, + /// Automatically create users if they do not exist. + #[serde(skip_serializing_if="Option::is_none")] + pub autocreate: Option, + #[updater(skip)] + #[serde(skip_serializing_if="Option::is_none")] + pub username_claim: Option, +}