From 6446a34972b060d5732e94a3345a3c54518b0ed9 Mon Sep 17 00:00:00 2001 From: Artem Goncharov Date: Tue, 16 Sep 2025 20:04:38 +0200 Subject: [PATCH] feat: Add keystone_ng idp and mapping --- openstack_cli/src/identity/v4.rs | 3 + .../v4/federation/identity_provider.rs | 63 ++++ .../src/identity/v4/federation/mapping.rs | 63 ++++ .../identity/v4/federation/mapping/create.rs | 259 +++++++++++++ .../identity/v4/federation/mapping/delete.rs | 91 +++++ .../identity/v4/federation/mapping/list.rs | 119 ++++++ .../src/identity/v4/federation/mapping/set.rs | 322 ++++++++++++++++ .../identity/v4/federation/mapping/show.rs | 94 +++++ .../src/identity/v4/federation/mod.rs | 56 +++ openstack_cli/src/identity/v4/user/mod.rs | 1 + .../src/identity/v4/user/passkey/register.rs | 41 +- openstack_cli/tests/identity/mod.rs | 2 + .../identity_provider/create_autogen.rs | 1 + .../identity_provider/delete_autogen.rs | 1 + .../identity_provider/list_autogen.rs | 1 + .../v4/federation/identity_provider/mod.rs | 32 ++ .../identity_provider/set_autogen.rs | 1 + .../identity_provider/show_autogen.rs | 1 + .../v4/federation/mapping/create_autogen.rs | 33 ++ .../v4/federation/mapping/delete_autogen.rs | 33 ++ .../v4/federation/mapping/list_autogen.rs | 33 ++ .../identity/v4/federation/mapping/mod.rs | 32 ++ .../v4/federation/mapping/set_autogen.rs | 33 ++ .../v4/federation/mapping/show_autogen.rs | 33 ++ .../tests/identity/v4/federation/mod.rs | 29 ++ openstack_cli/tests/identity/v4/mod.rs | 28 ++ .../src/api/identity/v4/federation.rs | 1 + .../src/api/identity/v4/federation/mapping.rs | 23 ++ .../identity/v4/federation/mapping/create.rs | 357 ++++++++++++++++++ .../identity/v4/federation/mapping/delete.rs | 178 +++++++++ .../api/identity/v4/federation/mapping/get.rs | 183 +++++++++ .../identity/v4/federation/mapping/list.rs | 205 ++++++++++ .../api/identity/v4/federation/mapping/set.rs | 327 ++++++++++++++++ openstack_types/src/identity/v4/federation.rs | 1 + .../src/identity/v4/federation/mapping.rs | 19 + .../v4/federation/mapping/response.rs | 22 ++ .../v4/federation/mapping/response/create.rs | 134 +++++++ .../v4/federation/mapping/response/get.rs | 134 +++++++ .../v4/federation/mapping/response/list.rs | 134 +++++++ .../v4/federation/mapping/response/set.rs | 134 +++++++ 40 files changed, 3234 insertions(+), 23 deletions(-) create mode 100644 openstack_cli/src/identity/v4/federation/identity_provider.rs create mode 100644 openstack_cli/src/identity/v4/federation/mapping.rs create mode 100644 openstack_cli/src/identity/v4/federation/mapping/create.rs create mode 100644 openstack_cli/src/identity/v4/federation/mapping/delete.rs create mode 100644 openstack_cli/src/identity/v4/federation/mapping/list.rs create mode 100644 openstack_cli/src/identity/v4/federation/mapping/set.rs create mode 100644 openstack_cli/src/identity/v4/federation/mapping/show.rs create mode 100644 openstack_cli/src/identity/v4/federation/mod.rs create mode 100644 openstack_cli/tests/identity/v4/federation/identity_provider/mod.rs create mode 100644 openstack_cli/tests/identity/v4/federation/mapping/create_autogen.rs create mode 100644 openstack_cli/tests/identity/v4/federation/mapping/delete_autogen.rs create mode 100644 openstack_cli/tests/identity/v4/federation/mapping/list_autogen.rs create mode 100644 openstack_cli/tests/identity/v4/federation/mapping/mod.rs create mode 100644 openstack_cli/tests/identity/v4/federation/mapping/set_autogen.rs create mode 100644 openstack_cli/tests/identity/v4/federation/mapping/show_autogen.rs create mode 100644 openstack_cli/tests/identity/v4/federation/mod.rs create mode 100644 openstack_cli/tests/identity/v4/mod.rs create mode 100644 openstack_sdk/src/api/identity/v4/federation/mapping.rs create mode 100644 openstack_sdk/src/api/identity/v4/federation/mapping/create.rs create mode 100644 openstack_sdk/src/api/identity/v4/federation/mapping/delete.rs create mode 100644 openstack_sdk/src/api/identity/v4/federation/mapping/get.rs create mode 100644 openstack_sdk/src/api/identity/v4/federation/mapping/list.rs create mode 100644 openstack_sdk/src/api/identity/v4/federation/mapping/set.rs create mode 100644 openstack_types/src/identity/v4/federation/mapping.rs create mode 100644 openstack_types/src/identity/v4/federation/mapping/response.rs create mode 100644 openstack_types/src/identity/v4/federation/mapping/response/create.rs create mode 100644 openstack_types/src/identity/v4/federation/mapping/response/get.rs create mode 100644 openstack_types/src/identity/v4/federation/mapping/response/list.rs create mode 100644 openstack_types/src/identity/v4/federation/mapping/response/set.rs diff --git a/openstack_cli/src/identity/v4.rs b/openstack_cli/src/identity/v4.rs index fd3bcbe3f..109ad5f1f 100644 --- a/openstack_cli/src/identity/v4.rs +++ b/openstack_cli/src/identity/v4.rs @@ -19,6 +19,7 @@ use openstack_sdk::AsyncOpenStack; use crate::{Cli, OpenStackCliError}; +pub mod federation; pub mod user; /// Identity (Keystone) commands @@ -46,6 +47,7 @@ pub struct IdentityCommand { #[allow(missing_docs)] #[derive(Subcommand)] pub enum IdentityCommands { + Federation(federation::FederationCommand), User(user::UserCommand), } @@ -57,6 +59,7 @@ impl IdentityCommand { session: &mut AsyncOpenStack, ) -> Result<(), OpenStackCliError> { match &self.command { + IdentityCommands::Federation(cmd) => cmd.take_action(parsed_args, session).await, IdentityCommands::User(cmd) => cmd.take_action(parsed_args, session).await, } } diff --git a/openstack_cli/src/identity/v4/federation/identity_provider.rs b/openstack_cli/src/identity/v4/federation/identity_provider.rs new file mode 100644 index 000000000..9aafcad8b --- /dev/null +++ b/openstack_cli/src/identity/v4/federation/identity_provider.rs @@ -0,0 +1,63 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +//! IdentityProvider Identity Provider commands + +use clap::{Parser, Subcommand}; + +use openstack_sdk::AsyncOpenStack; + +use crate::{Cli, OpenStackCliError}; + +pub mod create; +pub mod delete; +pub mod list; +pub mod set; +pub mod show; + +/// Federated identity provider commands +/// +#[derive(Parser)] +pub struct IdentityProviderCommand { + #[command(subcommand)] + command: IdentityProviderCommands, +} + +/// Supported subcommands +#[allow(missing_docs)] +#[derive(Subcommand)] +pub enum IdentityProviderCommands { + Create(create::IdentityProviderCommand), + Delete(delete::IdentityProviderCommand), + List(list::IdentityProvidersCommand), + Set(set::IdentityProviderCommand), + Show(show::IdentityProviderCommand), +} + +impl IdentityProviderCommand { + /// Perform command action + pub async fn take_action( + &self, + parsed_args: &Cli, + session: &mut AsyncOpenStack, + ) -> Result<(), OpenStackCliError> { + match &self.command { + IdentityProviderCommands::Create(cmd) => cmd.take_action(parsed_args, session).await, + IdentityProviderCommands::Delete(cmd) => cmd.take_action(parsed_args, session).await, + IdentityProviderCommands::List(cmd) => cmd.take_action(parsed_args, session).await, + IdentityProviderCommands::Set(cmd) => cmd.take_action(parsed_args, session).await, + IdentityProviderCommands::Show(cmd) => cmd.take_action(parsed_args, session).await, + } + } +} diff --git a/openstack_cli/src/identity/v4/federation/mapping.rs b/openstack_cli/src/identity/v4/federation/mapping.rs new file mode 100644 index 000000000..560a27c02 --- /dev/null +++ b/openstack_cli/src/identity/v4/federation/mapping.rs @@ -0,0 +1,63 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +//! Attribute Mapping commands + +use clap::{Parser, Subcommand}; + +use openstack_sdk::AsyncOpenStack; + +use crate::{Cli, OpenStackCliError}; + +pub mod create; +pub mod delete; +pub mod list; +pub mod set; +pub mod show; + +/// Federated attribute mapping commands +/// +#[derive(Parser)] +pub struct MappingCommand { + #[command(subcommand)] + command: MappingCommands, +} + +/// Supported subcommands +#[allow(missing_docs)] +#[derive(Subcommand)] +pub enum MappingCommands { + Create(create::MappingCommand), + Delete(delete::MappingCommand), + List(list::MappingsCommand), + Set(set::MappingCommand), + Show(show::MappingCommand), +} + +impl MappingCommand { + /// Perform command action + pub async fn take_action( + &self, + parsed_args: &Cli, + session: &mut AsyncOpenStack, + ) -> Result<(), OpenStackCliError> { + match &self.command { + MappingCommands::Create(cmd) => cmd.take_action(parsed_args, session).await, + MappingCommands::Delete(cmd) => cmd.take_action(parsed_args, session).await, + MappingCommands::List(cmd) => cmd.take_action(parsed_args, session).await, + MappingCommands::Set(cmd) => cmd.take_action(parsed_args, session).await, + MappingCommands::Show(cmd) => cmd.take_action(parsed_args, session).await, + } + } +} diff --git a/openstack_cli/src/identity/v4/federation/mapping/create.rs b/openstack_cli/src/identity/v4/federation/mapping/create.rs new file mode 100644 index 000000000..84276463c --- /dev/null +++ b/openstack_cli/src/identity/v4/federation/mapping/create.rs @@ -0,0 +1,259 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +//! Create Mapping command +//! +//! Wraps invoking of the `v4/federation/mappings` with `POST` method + +use clap::Args; +use tracing::info; + +use openstack_sdk::AsyncOpenStack; + +use crate::Cli; +use crate::OpenStackCliError; +use crate::output::OutputProcessor; + +use crate::common::parse_key_val; +use clap::ValueEnum; +use openstack_sdk::api::QueryAsync; +use openstack_sdk::api::identity::v4::federation::mapping::create; +use openstack_types::identity::v4::federation::mapping::response::create::MappingResponse; +use serde_json::Value; + +/// Command without description in OpenAPI +#[derive(Args)] +#[command(about = "Create attribute mapping.")] +pub struct MappingCommand { + /// Request Query parameters + #[command(flatten)] + query: QueryParameters, + + /// Path parameters + #[command(flatten)] + path: PathParameters, + + /// OIDC/JWT attribute mapping create data. + #[command(flatten)] + mapping: Mapping, +} + +/// Query parameters +#[derive(Args)] +struct QueryParameters {} + +/// Path parameters +#[derive(Args)] +struct PathParameters {} + +#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, ValueEnum)] +enum Type { + Jwt, + Oidc, +} + +/// Mapping Body data +#[derive(Args, Clone)] +struct Mapping { + /// List of allowed redirect urls (only for `oidc` type). + /// + /// Parameter is an array, may be provided multiple times. + #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)] + allowed_redirect_uris: Option>, + + /// List of audiences that must be present in the token. + /// + /// Parameter is an array, may be provided multiple times. + #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)] + bound_audiences: Option>, + + /// Additional claims that must be present in the token. + #[arg(help_heading = "Body parameters", long, value_name="key=value", value_parser=parse_key_val::)] + bound_claims: Option>, + + /// Token subject value that must be set in the token. + #[arg(help_heading = "Body parameters", long)] + bound_subject: Option, + + /// `domain_id` owning the attribute mapping. + /// + /// Unset `domain_id` means the attribute mapping is shared and can be used + /// by different domains. This requires `domain_id_claim` to be present. + /// Attribute mapping can be only shared when the referred identity + /// provider is also shared (does not set the `domain_id` attribute). + #[arg(help_heading = "Body parameters", long)] + domain_id: Option, + + /// `domain_id` claim name. + #[arg(help_heading = "Body parameters", long)] + domain_id_claim: Option, + + /// `groups` claim name. + #[arg(help_heading = "Body parameters", long)] + groups_claim: Option, + + /// Attribute mapping ID for federated logins. + #[arg(help_heading = "Body parameters", long)] + id: Option, + + /// Set explicit NULL for the id + #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "id")] + no_id: bool, + + /// ID of the federated identity provider for which this attribute mapping + /// can be used. + #[arg(help_heading = "Body parameters", long)] + idp_id: String, + + /// Attribute mapping name for federated logins. + #[arg(help_heading = "Body parameters", long)] + name: String, + + /// List of OIDC scopes. + /// + /// Parameter is an array, may be provided multiple times. + #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)] + oidc_scopes: Option>, + + /// Fixed project_id for the token. + #[arg(help_heading = "Body parameters", long)] + token_project_id: Option, + + /// List of fixed roles that would be included in the token. + /// + /// Parameter is an array, may be provided multiple times. + #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)] + token_role_ids: Option>, + + /// Fixed user_id for which the keystone token would be issued. + #[arg(help_heading = "Body parameters", long)] + token_user_id: Option, + + /// Attribute mapping type. + #[arg(help_heading = "Body parameters", long)] + _type: Option, + + /// `user_id` claim name. + #[arg(help_heading = "Body parameters", long)] + user_id_claim: String, + + /// `user_name` claim name. + #[arg(help_heading = "Body parameters", long)] + user_name_claim: String, +} + +impl MappingCommand { + /// Perform command action + pub async fn take_action( + &self, + parsed_args: &Cli, + client: &mut AsyncOpenStack, + ) -> Result<(), OpenStackCliError> { + info!("Create Mapping"); + + let op = OutputProcessor::from_args( + parsed_args, + Some("identity.federation/mapping"), + Some("create"), + ); + op.validate_args(parsed_args)?; + + let mut ep_builder = create::Request::builder(); + + // Set body parameters + // Set Request.mapping data + let args = &self.mapping; + let mut mapping_builder = create::MappingBuilder::default(); + if let Some(val) = &args.allowed_redirect_uris { + mapping_builder.allowed_redirect_uris(val.iter().map(Into::into).collect::>()); + } + + if let Some(val) = &args.bound_audiences { + mapping_builder.bound_audiences(val.iter().map(Into::into).collect::>()); + } + + if let Some(val) = &args.bound_claims { + mapping_builder.bound_claims(val.iter().cloned()); + } + + if let Some(val) = &args.bound_subject { + mapping_builder.bound_subject(val); + } + + if let Some(val) = &args.domain_id { + mapping_builder.domain_id(val); + } + + if let Some(val) = &args.domain_id_claim { + mapping_builder.domain_id_claim(val); + } + + if let Some(val) = &args.groups_claim { + mapping_builder.groups_claim(val); + } + + if let Some(val) = &args.id { + mapping_builder.id(Some(val.into())); + } else if args.no_id { + mapping_builder.id(None); + } + + mapping_builder.idp_id(&args.idp_id); + + mapping_builder.name(&args.name); + + if let Some(val) = &args.oidc_scopes { + mapping_builder.oidc_scopes(val.iter().map(Into::into).collect::>()); + } + + if let Some(val) = &args.token_project_id { + mapping_builder.token_project_id(val); + } + + if let Some(val) = &args.token_role_ids { + mapping_builder.token_role_ids(val.iter().map(Into::into).collect::>()); + } + + if let Some(val) = &args.token_user_id { + mapping_builder.token_user_id(val); + } + + if let Some(val) = &args._type { + let tmp = match val { + Type::Jwt => create::Type::Jwt, + Type::Oidc => create::Type::Oidc, + }; + mapping_builder._type(tmp); + } + + mapping_builder.user_id_claim(&args.user_id_claim); + + mapping_builder.user_name_claim(&args.user_name_claim); + + ep_builder.mapping(mapping_builder.build().unwrap()); + + let ep = ep_builder + .build() + .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?; + + let data = ep.query_async(client).await?; + op.output_single::(data)?; + // Show command specific hints + op.show_command_hint()?; + Ok(()) + } +} diff --git a/openstack_cli/src/identity/v4/federation/mapping/delete.rs b/openstack_cli/src/identity/v4/federation/mapping/delete.rs new file mode 100644 index 000000000..813cfcdff --- /dev/null +++ b/openstack_cli/src/identity/v4/federation/mapping/delete.rs @@ -0,0 +1,91 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +//! Delete Mapping command +//! +//! Wraps invoking of the `v4/federation/mappings/{id}` with `DELETE` method + +use clap::Args; +use tracing::info; + +use openstack_sdk::AsyncOpenStack; + +use crate::Cli; +use crate::OpenStackCliError; +use crate::output::OutputProcessor; + +use openstack_sdk::api::QueryAsync; +use openstack_sdk::api::identity::v4::federation::mapping::delete; + +/// Command without description in OpenAPI +#[derive(Args)] +#[command(about = "Delete attribute mapping.")] +pub struct MappingCommand { + /// Request Query parameters + #[command(flatten)] + query: QueryParameters, + + /// Path parameters + #[command(flatten)] + path: PathParameters, +} + +/// Query parameters +#[derive(Args)] +struct QueryParameters {} + +/// Path parameters +#[derive(Args)] +struct PathParameters { + /// The ID of the attribute mapping + #[arg( + help_heading = "Path parameters", + id = "path_param_id", + value_name = "ID" + )] + id: String, +} + +impl MappingCommand { + /// Perform command action + pub async fn take_action( + &self, + parsed_args: &Cli, + client: &mut AsyncOpenStack, + ) -> Result<(), OpenStackCliError> { + info!("Delete Mapping"); + + let op = OutputProcessor::from_args( + parsed_args, + Some("identity.federation/mapping"), + Some("delete"), + ); + op.validate_args(parsed_args)?; + + let mut ep_builder = delete::Request::builder(); + + ep_builder.id(&self.path.id); + + let ep = ep_builder + .build() + .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?; + openstack_sdk::api::ignore(ep).query_async(client).await?; + // Show command specific hints + op.show_command_hint()?; + Ok(()) + } +} diff --git a/openstack_cli/src/identity/v4/federation/mapping/list.rs b/openstack_cli/src/identity/v4/federation/mapping/list.rs new file mode 100644 index 000000000..18279af6e --- /dev/null +++ b/openstack_cli/src/identity/v4/federation/mapping/list.rs @@ -0,0 +1,119 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +//! List Mappings command +//! +//! Wraps invoking of the `v4/federation/mappings` with `GET` method + +use clap::Args; +use tracing::info; + +use openstack_sdk::AsyncOpenStack; + +use crate::Cli; +use crate::OpenStackCliError; +use crate::output::OutputProcessor; + +use openstack_sdk::api::QueryAsync; +use openstack_sdk::api::identity::v4::federation::mapping::list; +use openstack_types::identity::v4::federation::mapping::response::list::MappingResponse; + +/// List available federation mappings. +/// +/// Without `domain_id` specified global mappings are returned. +/// +/// It is expected that listing mappings belonging to the other domain is only +/// allowed to the admin user. +#[derive(Args)] +#[command(about = "List federation mappings.")] +pub struct MappingsCommand { + /// Request Query parameters + #[command(flatten)] + query: QueryParameters, + + /// Path parameters + #[command(flatten)] + path: PathParameters, +} + +/// Query parameters +#[derive(Args)] +struct QueryParameters { + /// Filters the response by a mapping type. + #[arg(help_heading = "Query parameters", long, value_parser = ["jwt","oidc"])] + _type: Option, + + /// Filters the response by a domain ID. + #[arg(help_heading = "Query parameters", long)] + domain_id: Option, + + /// Filters the response by a idp ID. + #[arg(help_heading = "Query parameters", long)] + idp_id: Option, + + /// Filters the response by IDP name. + #[arg(help_heading = "Query parameters", long)] + name: Option, +} + +/// Path parameters +#[derive(Args)] +struct PathParameters {} + +impl MappingsCommand { + /// Perform command action + pub async fn take_action( + &self, + parsed_args: &Cli, + client: &mut AsyncOpenStack, + ) -> Result<(), OpenStackCliError> { + info!("List Mappings"); + + let op = OutputProcessor::from_args( + parsed_args, + Some("identity.federation/mapping"), + Some("list"), + ); + op.validate_args(parsed_args)?; + + let mut ep_builder = list::Request::builder(); + + // Set query parameters + if let Some(val) = &self.query.name { + ep_builder.name(val); + } + if let Some(val) = &self.query.domain_id { + ep_builder.domain_id(val); + } + if let Some(val) = &self.query.idp_id { + ep_builder.idp_id(val); + } + if let Some(val) = &self.query._type { + ep_builder._type(val); + } + + let ep = ep_builder + .build() + .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?; + + let data: Vec = ep.query_async(client).await?; + op.output_list::(data)?; + // Show command specific hints + op.show_command_hint()?; + Ok(()) + } +} diff --git a/openstack_cli/src/identity/v4/federation/mapping/set.rs b/openstack_cli/src/identity/v4/federation/mapping/set.rs new file mode 100644 index 000000000..8fe6f8289 --- /dev/null +++ b/openstack_cli/src/identity/v4/federation/mapping/set.rs @@ -0,0 +1,322 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +//! Set Mapping command +//! +//! Wraps invoking of the `v4/federation/mappings/{id}` with `PUT` method + +use clap::Args; +use tracing::info; + +use openstack_sdk::AsyncOpenStack; + +use crate::Cli; +use crate::OpenStackCliError; +use crate::output::OutputProcessor; + +use crate::common::parse_key_val; +use clap::ValueEnum; +use openstack_sdk::api::QueryAsync; +use openstack_sdk::api::identity::v4::federation::mapping::set; +use openstack_types::identity::v4::federation::mapping::response::set::MappingResponse; +use serde_json::Value; + +/// TODO: describe domain_id update rules +#[derive(Args)] +#[command(about = "Update attribute mapping.")] +pub struct MappingCommand { + /// Request Query parameters + #[command(flatten)] + query: QueryParameters, + + /// Path parameters + #[command(flatten)] + path: PathParameters, + + /// OIDC/JWT attribute mapping update data. + #[command(flatten)] + mapping: Mapping, +} + +/// Query parameters +#[derive(Args)] +struct QueryParameters {} + +/// Path parameters +#[derive(Args)] +struct PathParameters { + /// The ID of the attribute mapping. + #[arg( + help_heading = "Path parameters", + id = "path_param_id", + value_name = "ID" + )] + id: String, +} + +#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, ValueEnum)] +enum Type { + Jwt, + Oidc, +} + +/// Mapping Body data +#[derive(Args, Clone)] +struct Mapping { + /// List of allowed redirect urls (only for `oidc` type). + /// + /// Parameter is an array, may be provided multiple times. + #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)] + allowed_redirect_uris: Option>, + + /// List of audiences that must be present in the token. + /// + /// Parameter is an array, may be provided multiple times. + #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)] + bound_audiences: Option>, + + /// Additional claims that must be present in the token. + #[arg(help_heading = "Body parameters", long, value_name="key=value", value_parser=parse_key_val::)] + bound_claims: Option>, + + /// Token subject value that must be set in the token. + #[arg(help_heading = "Body parameters", long)] + bound_subject: Option, + + /// Set explicit NULL for the bound_subject + #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "bound_subject")] + no_bound_subject: bool, + + /// `domain_id` owning the attribute mapping. + /// + /// Unset `domain_id` means the attribute mapping is shared and can be used + /// by different domains. This requires `domain_id_claim` to be present. + /// Attribute mapping can be only shared when the referred identity + /// provider is also shared (does not set the `domain_id` attribute). + #[arg(help_heading = "Body parameters", long)] + domain_id: Option, + + /// Set explicit NULL for the domain_id + #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "domain_id")] + no_domain_id: bool, + + #[arg(help_heading = "Body parameters", long)] + domain_id_claim: Option, + + /// Set explicit NULL for the domain_id_claim + #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "domain_id_claim")] + no_domain_id_claim: bool, + + /// `groups` claim name. + #[arg(help_heading = "Body parameters", long)] + groups_claim: Option, + + /// Set explicit NULL for the groups_claim + #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "groups_claim")] + no_groups_claim: bool, + + /// ID of the federated identity provider for which this attribute mapping + /// can be used. + #[arg(help_heading = "Body parameters", long)] + idp_id: Option, + + /// Set explicit NULL for the idp_id + #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "idp_id")] + no_idp_id: bool, + + /// Attribute mapping name for federated logins. + #[arg(help_heading = "Body parameters", long)] + name: Option, + + /// Set explicit NULL for the name + #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "name")] + no_name: bool, + + /// List of OIDC scopes. + /// + /// Parameter is an array, may be provided multiple times. + #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)] + oidc_scopes: Option>, + + /// Fixed project_id for the token. + #[arg(help_heading = "Body parameters", long)] + token_project_id: Option, + + /// Set explicit NULL for the token_project_id + #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "token_project_id")] + no_token_project_id: bool, + + /// List of fixed roles that would be included in the token. + /// + /// Parameter is an array, may be provided multiple times. + #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)] + token_role_ids: Option>, + + /// Fixed user_id for which the keystone token would be issued. + #[arg(help_heading = "Body parameters", long)] + token_user_id: Option, + + /// Set explicit NULL for the token_user_id + #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "token_user_id")] + no_token_user_id: bool, + + /// Attribute mapping type. + #[arg(help_heading = "Body parameters", long)] + _type: Option, + + /// `user_id` claim name. + #[arg(help_heading = "Body parameters", long)] + user_id_claim: Option, + + /// Set explicit NULL for the user_id_claim + #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "user_id_claim")] + no_user_id_claim: bool, + + /// `user_name` claim name. + #[arg(help_heading = "Body parameters", long)] + user_name_claim: Option, + + /// Set explicit NULL for the user_name_claim + #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "user_name_claim")] + no_user_name_claim: bool, +} + +impl MappingCommand { + /// Perform command action + pub async fn take_action( + &self, + parsed_args: &Cli, + client: &mut AsyncOpenStack, + ) -> Result<(), OpenStackCliError> { + info!("Set Mapping"); + + let op = OutputProcessor::from_args( + parsed_args, + Some("identity.federation/mapping"), + Some("set"), + ); + op.validate_args(parsed_args)?; + + let mut ep_builder = set::Request::builder(); + + ep_builder.id(&self.path.id); + + // Set body parameters + // Set Request.mapping data + let args = &self.mapping; + let mut mapping_builder = set::MappingBuilder::default(); + if let Some(val) = &args.allowed_redirect_uris { + mapping_builder.allowed_redirect_uris(val.iter().map(Into::into).collect::>()); + } + + if let Some(val) = &args.bound_audiences { + mapping_builder.bound_audiences(val.iter().map(Into::into).collect::>()); + } + + if let Some(val) = &args.bound_claims { + mapping_builder.bound_claims(val.iter().cloned()); + } + + if let Some(val) = &args.bound_subject { + mapping_builder.bound_subject(Some(val.into())); + } else if args.no_bound_subject { + mapping_builder.bound_subject(None); + } + + if let Some(val) = &args.domain_id { + mapping_builder.domain_id(Some(val.into())); + } else if args.no_domain_id { + mapping_builder.domain_id(None); + } + + if let Some(val) = &args.domain_id_claim { + mapping_builder.domain_id_claim(Some(val.into())); + } else if args.no_domain_id_claim { + mapping_builder.domain_id_claim(None); + } + + if let Some(val) = &args.groups_claim { + mapping_builder.groups_claim(Some(val.into())); + } else if args.no_groups_claim { + mapping_builder.groups_claim(None); + } + + if let Some(val) = &args.idp_id { + mapping_builder.idp_id(Some(val.into())); + } else if args.no_idp_id { + mapping_builder.idp_id(None); + } + + if let Some(val) = &args.name { + mapping_builder.name(Some(val.into())); + } else if args.no_name { + mapping_builder.name(None); + } + + if let Some(val) = &args.oidc_scopes { + mapping_builder.oidc_scopes(val.iter().map(Into::into).collect::>()); + } + + if let Some(val) = &args.token_project_id { + mapping_builder.token_project_id(Some(val.into())); + } else if args.no_token_project_id { + mapping_builder.token_project_id(None); + } + + if let Some(val) = &args.token_role_ids { + mapping_builder.token_role_ids(val.iter().map(Into::into).collect::>()); + } + + if let Some(val) = &args.token_user_id { + mapping_builder.token_user_id(Some(val.into())); + } else if args.no_token_user_id { + mapping_builder.token_user_id(None); + } + + if let Some(val) = &args._type { + let tmp = match val { + Type::Jwt => set::Type::Jwt, + Type::Oidc => set::Type::Oidc, + }; + mapping_builder._type(tmp); + } + + if let Some(val) = &args.user_id_claim { + mapping_builder.user_id_claim(Some(val.into())); + } else if args.no_user_id_claim { + mapping_builder.user_id_claim(None); + } + + if let Some(val) = &args.user_name_claim { + mapping_builder.user_name_claim(Some(val.into())); + } else if args.no_user_name_claim { + mapping_builder.user_name_claim(None); + } + + ep_builder.mapping(mapping_builder.build().unwrap()); + + let ep = ep_builder + .build() + .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?; + + let data = ep.query_async(client).await?; + op.output_single::(data)?; + // Show command specific hints + op.show_command_hint()?; + Ok(()) + } +} diff --git a/openstack_cli/src/identity/v4/federation/mapping/show.rs b/openstack_cli/src/identity/v4/federation/mapping/show.rs new file mode 100644 index 000000000..81ea0f533 --- /dev/null +++ b/openstack_cli/src/identity/v4/federation/mapping/show.rs @@ -0,0 +1,94 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +//! Show Mapping command +//! +//! Wraps invoking of the `v4/federation/mappings/{id}` with `GET` method + +use clap::Args; +use tracing::info; + +use openstack_sdk::AsyncOpenStack; + +use crate::Cli; +use crate::OpenStackCliError; +use crate::output::OutputProcessor; + +use openstack_sdk::api::QueryAsync; +use openstack_sdk::api::identity::v4::federation::mapping::get; +use openstack_types::identity::v4::federation::mapping::response::get::MappingResponse; + +/// Show the attribute mapping attribute by the ID. +#[derive(Args)] +#[command(about = "Get single mapping.")] +pub struct MappingCommand { + /// Request Query parameters + #[command(flatten)] + query: QueryParameters, + + /// Path parameters + #[command(flatten)] + path: PathParameters, +} + +/// Query parameters +#[derive(Args)] +struct QueryParameters {} + +/// Path parameters +#[derive(Args)] +struct PathParameters { + /// The ID of the attribute mapping. + #[arg( + help_heading = "Path parameters", + id = "path_param_id", + value_name = "ID" + )] + id: String, +} + +impl MappingCommand { + /// Perform command action + pub async fn take_action( + &self, + parsed_args: &Cli, + client: &mut AsyncOpenStack, + ) -> Result<(), OpenStackCliError> { + info!("Show Mapping"); + + let op = OutputProcessor::from_args( + parsed_args, + Some("identity.federation/mapping"), + Some("show"), + ); + op.validate_args(parsed_args)?; + + let mut ep_builder = get::Request::builder(); + + ep_builder.id(&self.path.id); + + let ep = ep_builder + .build() + .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?; + + let data = ep.query_async(client).await?; + op.output_single::(data)?; + // Show command specific hints + op.show_command_hint()?; + Ok(()) + } +} diff --git a/openstack_cli/src/identity/v4/federation/mod.rs b/openstack_cli/src/identity/v4/federation/mod.rs new file mode 100644 index 000000000..2240db8c6 --- /dev/null +++ b/openstack_cli/src/identity/v4/federation/mod.rs @@ -0,0 +1,56 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +//! Federation commands + +use clap::{Parser, Subcommand}; + +use openstack_sdk::AsyncOpenStack; + +use crate::{Cli, OpenStackCliError}; + +pub mod identity_provider; +pub mod mapping; + +/// Federated login commands +/// +#[derive(Parser)] +pub struct FederationCommand { + #[command(subcommand)] + command: FederationCommands, +} + +/// Supported subcommands +#[allow(missing_docs)] +#[derive(Subcommand)] +pub enum FederationCommands { + IdentityProvider(identity_provider::IdentityProviderCommand), + Mapping(mapping::MappingCommand), +} + +impl FederationCommand { + /// Perform command action + pub async fn take_action( + &self, + parsed_args: &Cli, + session: &mut AsyncOpenStack, + ) -> Result<(), OpenStackCliError> { + match &self.command { + FederationCommands::IdentityProvider(cmd) => { + cmd.take_action(parsed_args, session).await + } + FederationCommands::Mapping(cmd) => cmd.take_action(parsed_args, session).await, + } + } +} diff --git a/openstack_cli/src/identity/v4/user/mod.rs b/openstack_cli/src/identity/v4/user/mod.rs index b2bae7dec..d6522b837 100644 --- a/openstack_cli/src/identity/v4/user/mod.rs +++ b/openstack_cli/src/identity/v4/user/mod.rs @@ -49,6 +49,7 @@ impl UserCommand { match &self.command { #[cfg(feature = "passkey")] UserCommands::Passkey(cmd) => cmd.take_action(parsed_args, session).await, + _ => todo!(), } } } diff --git a/openstack_cli/src/identity/v4/user/passkey/register.rs b/openstack_cli/src/identity/v4/user/passkey/register.rs index 035869236..bf5b33d67 100644 --- a/openstack_cli/src/identity/v4/user/passkey/register.rs +++ b/openstack_cli/src/identity/v4/user/passkey/register.rs @@ -102,36 +102,33 @@ fn convert_api_response_to_public_key_credential_options( ) -> Result { Ok( webauthn_rs_proto::attest::PublicKeyCredentialCreationOptions { - attestation: val.attestation.map(|att| convert_attestation(att)), + attestation: val.attestation.map(convert_attestation), attestation_formats: val.attestation_formats.map(|ats| { ats.into_iter() - .map(|at| convert_attestation_format(at)) + .map(convert_attestation_format) .collect::>() }), authenticator_selection: val .authenticator_selection - .map(|authr| convert_authenticator_selection(authr)), + .map(convert_authenticator_selection), challenge: URL_SAFE.decode(val.challenge)?.into(), exclude_credentials: val .exclude_credentials .map(|ecs| { ecs.into_iter() - .map(|cred| convert_exclude_credential(cred)) + .map(convert_exclude_credential) //.transpose()? .collect::, _>>() }) .transpose()?, //.collect::>() - extensions: val.extensions.map(|ext| convert_extension(ext)), - hints: val.hints.map(|hints| { - hints - .into_iter() - .map(|hint| convert_hint(hint)) - .collect::>() - }), + extensions: val.extensions.map(convert_extension), + hints: val + .hints + .map(|hints| hints.into_iter().map(convert_hint).collect::>()), pub_key_cred_params: val .pub_key_cred_params .into_iter() - .map(|cp| convert_pub_key_cred_params(cp)) + .map(convert_pub_key_cred_params) .collect::>(), rp: convert_rp(val.rp), timeout: val.timeout, @@ -189,8 +186,8 @@ fn convert_authenticator_selection( webauthn_rs_proto::options::AuthenticatorSelectionCriteria { authenticator_attachment: val .authenticator_attachment - .map(|authra| convert_authenticator_attachment(authra)), - resident_key: val.resident_key.map(|key| convert_resident_key(key)), + .map(convert_authenticator_attachment), + resident_key: val.resident_key.map(convert_resident_key), require_resident_key: val.require_resident_key, user_verification: convert_user_verification(val.user_verification), } @@ -251,11 +248,9 @@ fn convert_exclude_credential( Ok(webauthn_rs_proto::options::PublicKeyCredentialDescriptor { id: URL_SAFE.decode(val.id)?.into(), type_: val.type_, - transports: val.transports.map(|trs| { - trs.into_iter() - .map(|tr| convert_transport(tr)) - .collect::>() - }), + transports: val + .transports + .map(|trs| trs.into_iter().map(convert_transport).collect::>()), }) } @@ -320,7 +315,7 @@ fn convert_extension( ) -> webauthn_rs_proto::extensions::RequestRegistrationExtensions { webauthn_rs_proto::extensions::RequestRegistrationExtensions { cred_props: val.cred_props, - cred_protect: val.cred_protect.map(|cp| convert_cred_protect(cp)), + cred_protect: val.cred_protect.map(convert_cred_protect), hmac_create_secret: val.hmac_create_secret, min_pin_length: val.min_pin_length, uvm: val.uvm, @@ -401,7 +396,7 @@ fn get_finish_registration_endpoint( rsp.transports( transports .into_iter() - .map(|tr| convert_transport_webauthn_to_keystone(tr)) + .map(convert_transport_webauthn_to_keystone) .collect::>(), ); } @@ -442,9 +437,9 @@ fn get_finish_registration_endpoint( .wrap_err_with(|| eyre!("cannot build passkey `extensions` structure"))?, ); - Ok(builder + builder .build() - .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?) + .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string())) } impl PasskeyCommand { diff --git a/openstack_cli/tests/identity/mod.rs b/openstack_cli/tests/identity/mod.rs index 8e046c72c..f8411e6b4 100644 --- a/openstack_cli/tests/identity/mod.rs +++ b/openstack_cli/tests/identity/mod.rs @@ -13,3 +13,5 @@ // SPDX-License-Identifier: Apache-2.0 mod v3; +#[cfg(feature = "keystone_ng")] +mod v4; diff --git a/openstack_cli/tests/identity/v4/federation/identity_provider/create_autogen.rs b/openstack_cli/tests/identity/v4/federation/identity_provider/create_autogen.rs index 6b845a61a..3793a0fb7 100644 --- a/openstack_cli/tests/identity/v4/federation/identity_provider/create_autogen.rs +++ b/openstack_cli/tests/identity/v4/federation/identity_provider/create_autogen.rs @@ -23,6 +23,7 @@ fn help() -> Result<(), Box> { let mut cmd = Command::cargo_bin("osc")?; cmd.arg("identity") + .arg("federation") .arg("identity-provider") .arg("create") .arg("--help"); diff --git a/openstack_cli/tests/identity/v4/federation/identity_provider/delete_autogen.rs b/openstack_cli/tests/identity/v4/federation/identity_provider/delete_autogen.rs index cc82b2365..160bc4232 100644 --- a/openstack_cli/tests/identity/v4/federation/identity_provider/delete_autogen.rs +++ b/openstack_cli/tests/identity/v4/federation/identity_provider/delete_autogen.rs @@ -23,6 +23,7 @@ fn help() -> Result<(), Box> { let mut cmd = Command::cargo_bin("osc")?; cmd.arg("identity") + .arg("federation") .arg("identity-provider") .arg("delete") .arg("--help"); diff --git a/openstack_cli/tests/identity/v4/federation/identity_provider/list_autogen.rs b/openstack_cli/tests/identity/v4/federation/identity_provider/list_autogen.rs index 12d4fd400..f8ee17fcd 100644 --- a/openstack_cli/tests/identity/v4/federation/identity_provider/list_autogen.rs +++ b/openstack_cli/tests/identity/v4/federation/identity_provider/list_autogen.rs @@ -23,6 +23,7 @@ fn help() -> Result<(), Box> { let mut cmd = Command::cargo_bin("osc")?; cmd.arg("identity") + .arg("federation") .arg("identity-provider") .arg("list") .arg("--help"); diff --git a/openstack_cli/tests/identity/v4/federation/identity_provider/mod.rs b/openstack_cli/tests/identity/v4/federation/identity_provider/mod.rs new file mode 100644 index 000000000..8dd825f49 --- /dev/null +++ b/openstack_cli/tests/identity/v4/federation/identity_provider/mod.rs @@ -0,0 +1,32 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +mod create_autogen; +mod delete_autogen; +mod list_autogen; +mod set_autogen; +mod show_autogen; + +use assert_cmd::prelude::*; +use std::process::Command; + +#[test] +fn help() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("osc")?; + + cmd.args(["identity4", "federation", "identity-provider", "--help"]); + cmd.assert().success(); + + Ok(()) +} diff --git a/openstack_cli/tests/identity/v4/federation/identity_provider/set_autogen.rs b/openstack_cli/tests/identity/v4/federation/identity_provider/set_autogen.rs index 96438338f..c98697e72 100644 --- a/openstack_cli/tests/identity/v4/federation/identity_provider/set_autogen.rs +++ b/openstack_cli/tests/identity/v4/federation/identity_provider/set_autogen.rs @@ -23,6 +23,7 @@ fn help() -> Result<(), Box> { let mut cmd = Command::cargo_bin("osc")?; cmd.arg("identity") + .arg("federation") .arg("identity-provider") .arg("set") .arg("--help"); diff --git a/openstack_cli/tests/identity/v4/federation/identity_provider/show_autogen.rs b/openstack_cli/tests/identity/v4/federation/identity_provider/show_autogen.rs index 56e01ca92..d700cee7d 100644 --- a/openstack_cli/tests/identity/v4/federation/identity_provider/show_autogen.rs +++ b/openstack_cli/tests/identity/v4/federation/identity_provider/show_autogen.rs @@ -23,6 +23,7 @@ fn help() -> Result<(), Box> { let mut cmd = Command::cargo_bin("osc")?; cmd.arg("identity") + .arg("federation") .arg("identity-provider") .arg("show") .arg("--help"); diff --git a/openstack_cli/tests/identity/v4/federation/mapping/create_autogen.rs b/openstack_cli/tests/identity/v4/federation/mapping/create_autogen.rs new file mode 100644 index 000000000..b293a1a39 --- /dev/null +++ b/openstack_cli/tests/identity/v4/federation/mapping/create_autogen.rs @@ -0,0 +1,33 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +use assert_cmd::prelude::*; +use std::process::Command; + +#[test] +fn help() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("osc")?; + + cmd.arg("identity") + .arg("federation") + .arg("mapping") + .arg("create") + .arg("--help"); + cmd.assert().success(); + + Ok(()) +} diff --git a/openstack_cli/tests/identity/v4/federation/mapping/delete_autogen.rs b/openstack_cli/tests/identity/v4/federation/mapping/delete_autogen.rs new file mode 100644 index 000000000..d64e3576d --- /dev/null +++ b/openstack_cli/tests/identity/v4/federation/mapping/delete_autogen.rs @@ -0,0 +1,33 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +use assert_cmd::prelude::*; +use std::process::Command; + +#[test] +fn help() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("osc")?; + + cmd.arg("identity") + .arg("federation") + .arg("mapping") + .arg("delete") + .arg("--help"); + cmd.assert().success(); + + Ok(()) +} diff --git a/openstack_cli/tests/identity/v4/federation/mapping/list_autogen.rs b/openstack_cli/tests/identity/v4/federation/mapping/list_autogen.rs new file mode 100644 index 000000000..42ba24dea --- /dev/null +++ b/openstack_cli/tests/identity/v4/federation/mapping/list_autogen.rs @@ -0,0 +1,33 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +use assert_cmd::prelude::*; +use std::process::Command; + +#[test] +fn help() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("osc")?; + + cmd.arg("identity") + .arg("federation") + .arg("mapping") + .arg("list") + .arg("--help"); + cmd.assert().success(); + + Ok(()) +} diff --git a/openstack_cli/tests/identity/v4/federation/mapping/mod.rs b/openstack_cli/tests/identity/v4/federation/mapping/mod.rs new file mode 100644 index 000000000..a26022443 --- /dev/null +++ b/openstack_cli/tests/identity/v4/federation/mapping/mod.rs @@ -0,0 +1,32 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +mod create_autogen; +mod delete_autogen; +mod list_autogen; +mod set_autogen; +mod show_autogen; + +use assert_cmd::prelude::*; +use std::process::Command; + +#[test] +fn help() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("osc")?; + + cmd.args(["identity4", "federation", "mapping", "--help"]); + cmd.assert().success(); + + Ok(()) +} diff --git a/openstack_cli/tests/identity/v4/federation/mapping/set_autogen.rs b/openstack_cli/tests/identity/v4/federation/mapping/set_autogen.rs new file mode 100644 index 000000000..05e101ec7 --- /dev/null +++ b/openstack_cli/tests/identity/v4/federation/mapping/set_autogen.rs @@ -0,0 +1,33 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +use assert_cmd::prelude::*; +use std::process::Command; + +#[test] +fn help() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("osc")?; + + cmd.arg("identity") + .arg("federation") + .arg("mapping") + .arg("set") + .arg("--help"); + cmd.assert().success(); + + Ok(()) +} diff --git a/openstack_cli/tests/identity/v4/federation/mapping/show_autogen.rs b/openstack_cli/tests/identity/v4/federation/mapping/show_autogen.rs new file mode 100644 index 000000000..a41e5ad60 --- /dev/null +++ b/openstack_cli/tests/identity/v4/federation/mapping/show_autogen.rs @@ -0,0 +1,33 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +use assert_cmd::prelude::*; +use std::process::Command; + +#[test] +fn help() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("osc")?; + + cmd.arg("identity") + .arg("federation") + .arg("mapping") + .arg("show") + .arg("--help"); + cmd.assert().success(); + + Ok(()) +} diff --git a/openstack_cli/tests/identity/v4/federation/mod.rs b/openstack_cli/tests/identity/v4/federation/mod.rs new file mode 100644 index 000000000..699bc1c19 --- /dev/null +++ b/openstack_cli/tests/identity/v4/federation/mod.rs @@ -0,0 +1,29 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +mod identity_provider; +mod mapping; + +use assert_cmd::prelude::*; +use std::process::Command; + +#[test] +fn help() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("osc")?; + + cmd.args(["identity4", "federation", "--help"]); + cmd.assert().success(); + + Ok(()) +} diff --git a/openstack_cli/tests/identity/v4/mod.rs b/openstack_cli/tests/identity/v4/mod.rs new file mode 100644 index 000000000..08ff42fde --- /dev/null +++ b/openstack_cli/tests/identity/v4/mod.rs @@ -0,0 +1,28 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +mod federation; + +use assert_cmd::prelude::*; +use std::process::Command; + +#[test] +fn help() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("osc")?; + + cmd.args(["identity4", "--help"]); + cmd.assert().success(); + + Ok(()) +} diff --git a/openstack_sdk/src/api/identity/v4/federation.rs b/openstack_sdk/src/api/identity/v4/federation.rs index 94801e23e..5fe26e49d 100644 --- a/openstack_sdk/src/api/identity/v4/federation.rs +++ b/openstack_sdk/src/api/identity/v4/federation.rs @@ -17,3 +17,4 @@ //! `/v4/federation/identity_providers/{idp_id}` REST operations of identity pub mod identity_provider; +pub mod mapping; diff --git a/openstack_sdk/src/api/identity/v4/federation/mapping.rs b/openstack_sdk/src/api/identity/v4/federation/mapping.rs new file mode 100644 index 000000000..9395d46eb --- /dev/null +++ b/openstack_sdk/src/api/identity/v4/federation/mapping.rs @@ -0,0 +1,23 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +//! `/v4/federation/mappings` REST operations of identity +pub mod create; +pub mod delete; +pub mod get; +pub mod list; +pub mod set; diff --git a/openstack_sdk/src/api/identity/v4/federation/mapping/create.rs b/openstack_sdk/src/api/identity/v4/federation/mapping/create.rs new file mode 100644 index 000000000..8334d4c49 --- /dev/null +++ b/openstack_sdk/src/api/identity/v4/federation/mapping/create.rs @@ -0,0 +1,357 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +use derive_builder::Builder; +use http::{HeaderMap, HeaderName, HeaderValue}; + +use crate::api::rest_endpoint_prelude::*; + +use serde::Deserialize; +use serde::Serialize; +use serde_json::Value; +use std::borrow::Cow; +use std::collections::BTreeMap; + +#[derive(Debug, Deserialize, Clone, Serialize)] +pub enum Type { + #[serde(rename = "jwt")] + Jwt, + #[serde(rename = "oidc")] + Oidc, +} + +/// OIDC/JWT attribute mapping create data. +#[derive(Builder, Debug, Deserialize, Clone, Serialize)] +#[builder(setter(strip_option))] +pub struct Mapping<'a> { + /// List of allowed redirect urls (only for `oidc` type). + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) allowed_redirect_uris: Option>>, + + /// List of audiences that must be present in the token. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) bound_audiences: Option>>, + + /// Additional claims that must be present in the token. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, private, setter(into, name = "_bound_claims"))] + pub(crate) bound_claims: Option, Value>>, + + /// Token subject value that must be set in the token. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) bound_subject: Option>, + + /// `domain_id` owning the attribute mapping. + /// + /// Unset `domain_id` means the attribute mapping is shared and can be used + /// by different domains. This requires `domain_id_claim` to be present. + /// Attribute mapping can be only shared when the referred identity + /// provider is also shared (does not set the `domain_id` attribute). + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) domain_id: Option>, + + /// `domain_id` claim name. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) domain_id_claim: Option>, + + /// `groups` claim name. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) groups_claim: Option>, + + /// Attribute mapping ID for federated logins. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) id: Option>>, + + /// ID of the federated identity provider for which this attribute mapping + /// can be used. + #[serde()] + #[builder(setter(into))] + pub(crate) idp_id: Cow<'a, str>, + + /// Attribute mapping name for federated logins. + #[serde()] + #[builder(setter(into))] + pub(crate) name: Cow<'a, str>, + + /// List of OIDC scopes. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) oidc_scopes: Option>>, + + /// Fixed project_id for the token. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) token_project_id: Option>, + + /// List of fixed roles that would be included in the token. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) token_role_ids: Option>>, + + /// Fixed user_id for which the keystone token would be issued. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) token_user_id: Option>, + + /// Attribute mapping type. + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + #[builder(default)] + pub(crate) _type: Option, + + /// `user_id` claim name. + #[serde()] + #[builder(setter(into))] + pub(crate) user_id_claim: Cow<'a, str>, + + /// `user_name` claim name. + #[serde()] + #[builder(setter(into))] + pub(crate) user_name_claim: Cow<'a, str>, +} + +impl<'a> MappingBuilder<'a> { + /// Additional claims that must be present in the token. + pub fn bound_claims(&mut self, iter: I) -> &mut Self + where + I: Iterator, + K: Into>, + V: Into, + { + self.bound_claims + .get_or_insert(None) + .get_or_insert_with(BTreeMap::new) + .extend(iter.map(|(k, v)| (k.into(), v.into()))); + self + } +} + +#[derive(Builder, Debug, Clone)] +#[builder(setter(strip_option))] +pub struct Request<'a> { + /// OIDC/JWT attribute mapping create data. + #[builder(setter(into))] + pub(crate) mapping: Mapping<'a>, + + #[builder(setter(name = "_headers"), default, private)] + _headers: Option, +} +impl<'a> Request<'a> { + /// Create a builder for the endpoint. + pub fn builder() -> RequestBuilder<'a> { + RequestBuilder::default() + } +} + +impl<'a> RequestBuilder<'a> { + /// Add a single header to the Mapping. + pub fn header(&mut self, header_name: K, header_value: V) -> &mut Self + where + K: Into, + V: Into, + { + self._headers + .get_or_insert(None) + .get_or_insert_with(HeaderMap::new) + .insert(header_name.into(), header_value.into()); + self + } + + /// Add multiple headers. + pub fn headers(&mut self, iter: I) -> &mut Self + where + I: Iterator, + T: Into<(Option, HeaderValue)>, + { + self._headers + .get_or_insert(None) + .get_or_insert_with(HeaderMap::new) + .extend(iter.map(Into::into)); + self + } +} + +impl RestEndpoint for Request<'_> { + fn method(&self) -> http::Method { + http::Method::POST + } + + fn endpoint(&self) -> Cow<'static, str> { + "federation/mappings".to_string().into() + } + + fn parameters(&self) -> QueryParams<'_> { + QueryParams::default() + } + + fn body(&self) -> Result)>, BodyError> { + let mut params = JsonBodyParams::default(); + + params.push("mapping", serde_json::to_value(&self.mapping)?); + + params.into_body() + } + + fn service_type(&self) -> ServiceType { + ServiceType::Identity + } + + fn response_key(&self) -> Option> { + Some("mapping".into()) + } + + /// Returns headers to be set into the request + fn request_headers(&self) -> Option<&HeaderMap> { + self._headers.as_ref() + } + + /// Returns required API version + fn api_version(&self) -> Option { + Some(ApiVersion::new(4, 0)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[cfg(feature = "sync")] + use crate::api::Query; + use crate::test::client::FakeOpenStackClient; + use crate::types::ServiceType; + use http::{HeaderName, HeaderValue}; + use httpmock::MockServer; + use serde_json::json; + + #[test] + fn test_service_type() { + assert_eq!( + Request::builder() + .mapping( + MappingBuilder::default() + .idp_id("foo") + .name("foo") + .user_id_claim("foo") + .user_name_claim("foo") + .build() + .unwrap() + ) + .build() + .unwrap() + .service_type(), + ServiceType::Identity + ); + } + + #[test] + fn test_response_key() { + assert_eq!( + Request::builder() + .mapping( + MappingBuilder::default() + .idp_id("foo") + .name("foo") + .user_id_claim("foo") + .user_name_claim("foo") + .build() + .unwrap() + ) + .build() + .unwrap() + .response_key() + .unwrap(), + "mapping" + ); + } + + #[cfg(feature = "sync")] + #[test] + fn endpoint() { + let server = MockServer::start(); + let client = FakeOpenStackClient::new(server.base_url()); + let mock = server.mock(|when, then| { + when.method(httpmock::Method::POST) + .path("/federation/mappings".to_string()); + + then.status(200) + .header("content-type", "application/json") + .json_body(json!({ "mapping": {} })); + }); + + let endpoint = Request::builder() + .mapping( + MappingBuilder::default() + .idp_id("foo") + .name("foo") + .user_id_claim("foo") + .user_name_claim("foo") + .build() + .unwrap(), + ) + .build() + .unwrap(); + let _: serde_json::Value = endpoint.query(&client).unwrap(); + mock.assert(); + } + + #[cfg(feature = "sync")] + #[test] + fn endpoint_headers() { + let server = MockServer::start(); + let client = FakeOpenStackClient::new(server.base_url()); + let mock = server.mock(|when, then| { + when.method(httpmock::Method::POST) + .path("/federation/mappings".to_string()) + .header("foo", "bar") + .header("not_foo", "not_bar"); + then.status(200) + .header("content-type", "application/json") + .json_body(json!({ "mapping": {} })); + }); + + let endpoint = Request::builder() + .mapping( + MappingBuilder::default() + .idp_id("foo") + .name("foo") + .user_id_claim("foo") + .user_name_claim("foo") + .build() + .unwrap(), + ) + .headers( + [( + Some(HeaderName::from_static("foo")), + HeaderValue::from_static("bar"), + )] + .into_iter(), + ) + .header( + HeaderName::from_static("not_foo"), + HeaderValue::from_static("not_bar"), + ) + .build() + .unwrap(); + let _: serde_json::Value = endpoint.query(&client).unwrap(); + mock.assert(); + } +} diff --git a/openstack_sdk/src/api/identity/v4/federation/mapping/delete.rs b/openstack_sdk/src/api/identity/v4/federation/mapping/delete.rs new file mode 100644 index 000000000..6edd106fd --- /dev/null +++ b/openstack_sdk/src/api/identity/v4/federation/mapping/delete.rs @@ -0,0 +1,178 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +use derive_builder::Builder; +use http::{HeaderMap, HeaderName, HeaderValue}; + +use crate::api::rest_endpoint_prelude::*; + +use std::borrow::Cow; + +#[derive(Builder, Debug, Clone)] +#[builder(setter(strip_option))] +pub struct Request<'a> { + /// The ID of the attribute mapping + #[builder(default, setter(into))] + id: Cow<'a, str>, + + #[builder(setter(name = "_headers"), default, private)] + _headers: Option, +} +impl<'a> Request<'a> { + /// Create a builder for the endpoint. + pub fn builder() -> RequestBuilder<'a> { + RequestBuilder::default() + } +} + +impl<'a> RequestBuilder<'a> { + /// Add a single header to the Mapping. + pub fn header(&mut self, header_name: K, header_value: V) -> &mut Self + where + K: Into, + V: Into, + { + self._headers + .get_or_insert(None) + .get_or_insert_with(HeaderMap::new) + .insert(header_name.into(), header_value.into()); + self + } + + /// Add multiple headers. + pub fn headers(&mut self, iter: I) -> &mut Self + where + I: Iterator, + T: Into<(Option, HeaderValue)>, + { + self._headers + .get_or_insert(None) + .get_or_insert_with(HeaderMap::new) + .extend(iter.map(Into::into)); + self + } +} + +impl RestEndpoint for Request<'_> { + fn method(&self) -> http::Method { + http::Method::DELETE + } + + fn endpoint(&self) -> Cow<'static, str> { + format!("federation/mappings/{id}", id = self.id.as_ref(),).into() + } + + fn parameters(&self) -> QueryParams<'_> { + QueryParams::default() + } + + fn service_type(&self) -> ServiceType { + ServiceType::Identity + } + + fn response_key(&self) -> Option> { + None + } + + /// Returns headers to be set into the request + fn request_headers(&self) -> Option<&HeaderMap> { + self._headers.as_ref() + } + + /// Returns required API version + fn api_version(&self) -> Option { + Some(ApiVersion::new(4, 0)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[cfg(feature = "sync")] + use crate::api::Query; + use crate::test::client::FakeOpenStackClient; + use crate::types::ServiceType; + use http::{HeaderName, HeaderValue}; + use httpmock::MockServer; + use serde_json::json; + + #[test] + fn test_service_type() { + assert_eq!( + Request::builder().build().unwrap().service_type(), + ServiceType::Identity + ); + } + + #[test] + fn test_response_key() { + assert!(Request::builder().build().unwrap().response_key().is_none()) + } + + #[cfg(feature = "sync")] + #[test] + fn endpoint() { + let server = MockServer::start(); + let client = FakeOpenStackClient::new(server.base_url()); + let mock = server.mock(|when, then| { + when.method(httpmock::Method::DELETE) + .path(format!("/federation/mappings/{id}", id = "id",)); + + then.status(200) + .header("content-type", "application/json") + .json_body(json!({ "dummy": {} })); + }); + + let endpoint = Request::builder().id("id").build().unwrap(); + let _: serde_json::Value = endpoint.query(&client).unwrap(); + mock.assert(); + } + + #[cfg(feature = "sync")] + #[test] + fn endpoint_headers() { + let server = MockServer::start(); + let client = FakeOpenStackClient::new(server.base_url()); + let mock = server.mock(|when, then| { + when.method(httpmock::Method::DELETE) + .path(format!("/federation/mappings/{id}", id = "id",)) + .header("foo", "bar") + .header("not_foo", "not_bar"); + then.status(200) + .header("content-type", "application/json") + .json_body(json!({ "dummy": {} })); + }); + + let endpoint = Request::builder() + .id("id") + .headers( + [( + Some(HeaderName::from_static("foo")), + HeaderValue::from_static("bar"), + )] + .into_iter(), + ) + .header( + HeaderName::from_static("not_foo"), + HeaderValue::from_static("not_bar"), + ) + .build() + .unwrap(); + let _: serde_json::Value = endpoint.query(&client).unwrap(); + mock.assert(); + } +} diff --git a/openstack_sdk/src/api/identity/v4/federation/mapping/get.rs b/openstack_sdk/src/api/identity/v4/federation/mapping/get.rs new file mode 100644 index 000000000..7719b1650 --- /dev/null +++ b/openstack_sdk/src/api/identity/v4/federation/mapping/get.rs @@ -0,0 +1,183 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +//! Show the attribute mapping attribute by the ID. +//! +use derive_builder::Builder; +use http::{HeaderMap, HeaderName, HeaderValue}; + +use crate::api::rest_endpoint_prelude::*; + +use std::borrow::Cow; + +#[derive(Builder, Debug, Clone)] +#[builder(setter(strip_option))] +pub struct Request<'a> { + /// The ID of the attribute mapping. + #[builder(default, setter(into))] + id: Cow<'a, str>, + + #[builder(setter(name = "_headers"), default, private)] + _headers: Option, +} +impl<'a> Request<'a> { + /// Create a builder for the endpoint. + pub fn builder() -> RequestBuilder<'a> { + RequestBuilder::default() + } +} + +impl<'a> RequestBuilder<'a> { + /// Add a single header to the Mapping. + pub fn header(&mut self, header_name: K, header_value: V) -> &mut Self + where + K: Into, + V: Into, + { + self._headers + .get_or_insert(None) + .get_or_insert_with(HeaderMap::new) + .insert(header_name.into(), header_value.into()); + self + } + + /// Add multiple headers. + pub fn headers(&mut self, iter: I) -> &mut Self + where + I: Iterator, + T: Into<(Option, HeaderValue)>, + { + self._headers + .get_or_insert(None) + .get_or_insert_with(HeaderMap::new) + .extend(iter.map(Into::into)); + self + } +} + +impl RestEndpoint for Request<'_> { + fn method(&self) -> http::Method { + http::Method::GET + } + + fn endpoint(&self) -> Cow<'static, str> { + format!("federation/mappings/{id}", id = self.id.as_ref(),).into() + } + + fn parameters(&self) -> QueryParams<'_> { + QueryParams::default() + } + + fn service_type(&self) -> ServiceType { + ServiceType::Identity + } + + fn response_key(&self) -> Option> { + Some("mapping".into()) + } + + /// Returns headers to be set into the request + fn request_headers(&self) -> Option<&HeaderMap> { + self._headers.as_ref() + } + + /// Returns required API version + fn api_version(&self) -> Option { + Some(ApiVersion::new(4, 0)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[cfg(feature = "sync")] + use crate::api::Query; + use crate::test::client::FakeOpenStackClient; + use crate::types::ServiceType; + use http::{HeaderName, HeaderValue}; + use httpmock::MockServer; + use serde_json::json; + + #[test] + fn test_service_type() { + assert_eq!( + Request::builder().build().unwrap().service_type(), + ServiceType::Identity + ); + } + + #[test] + fn test_response_key() { + assert_eq!( + Request::builder().build().unwrap().response_key().unwrap(), + "mapping" + ); + } + + #[cfg(feature = "sync")] + #[test] + fn endpoint() { + let server = MockServer::start(); + let client = FakeOpenStackClient::new(server.base_url()); + let mock = server.mock(|when, then| { + when.method(httpmock::Method::GET) + .path(format!("/federation/mappings/{id}", id = "id",)); + + then.status(200) + .header("content-type", "application/json") + .json_body(json!({ "mapping": {} })); + }); + + let endpoint = Request::builder().id("id").build().unwrap(); + let _: serde_json::Value = endpoint.query(&client).unwrap(); + mock.assert(); + } + + #[cfg(feature = "sync")] + #[test] + fn endpoint_headers() { + let server = MockServer::start(); + let client = FakeOpenStackClient::new(server.base_url()); + let mock = server.mock(|when, then| { + when.method(httpmock::Method::GET) + .path(format!("/federation/mappings/{id}", id = "id",)) + .header("foo", "bar") + .header("not_foo", "not_bar"); + then.status(200) + .header("content-type", "application/json") + .json_body(json!({ "mapping": {} })); + }); + + let endpoint = Request::builder() + .id("id") + .headers( + [( + Some(HeaderName::from_static("foo")), + HeaderValue::from_static("bar"), + )] + .into_iter(), + ) + .header( + HeaderName::from_static("not_foo"), + HeaderValue::from_static("not_bar"), + ) + .build() + .unwrap(); + let _: serde_json::Value = endpoint.query(&client).unwrap(); + mock.assert(); + } +} diff --git a/openstack_sdk/src/api/identity/v4/federation/mapping/list.rs b/openstack_sdk/src/api/identity/v4/federation/mapping/list.rs new file mode 100644 index 000000000..765d5fd87 --- /dev/null +++ b/openstack_sdk/src/api/identity/v4/federation/mapping/list.rs @@ -0,0 +1,205 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +//! List available federation mappings. +//! +//! Without `domain_id` specified global mappings are returned. +//! +//! It is expected that listing mappings belonging to the other domain is only +//! allowed to the admin user. +//! +use derive_builder::Builder; +use http::{HeaderMap, HeaderName, HeaderValue}; + +use crate::api::rest_endpoint_prelude::*; + +use std::borrow::Cow; + +#[derive(Builder, Debug, Clone)] +#[builder(setter(strip_option))] +pub struct Request<'a> { + /// Filters the response by a mapping type. + #[builder(default, setter(into))] + _type: Option>, + + /// Filters the response by a domain ID. + #[builder(default, setter(into))] + domain_id: Option>, + + /// Filters the response by a idp ID. + #[builder(default, setter(into))] + idp_id: Option>, + + /// Filters the response by IDP name. + #[builder(default, setter(into))] + name: Option>, + + #[builder(setter(name = "_headers"), default, private)] + _headers: Option, +} +impl<'a> Request<'a> { + /// Create a builder for the endpoint. + pub fn builder() -> RequestBuilder<'a> { + RequestBuilder::default() + } +} + +impl<'a> RequestBuilder<'a> { + /// Add a single header to the Mapping. + pub fn header(&mut self, header_name: K, header_value: V) -> &mut Self + where + K: Into, + V: Into, + { + self._headers + .get_or_insert(None) + .get_or_insert_with(HeaderMap::new) + .insert(header_name.into(), header_value.into()); + self + } + + /// Add multiple headers. + pub fn headers(&mut self, iter: I) -> &mut Self + where + I: Iterator, + T: Into<(Option, HeaderValue)>, + { + self._headers + .get_or_insert(None) + .get_or_insert_with(HeaderMap::new) + .extend(iter.map(Into::into)); + self + } +} + +impl RestEndpoint for Request<'_> { + fn method(&self) -> http::Method { + http::Method::GET + } + + fn endpoint(&self) -> Cow<'static, str> { + "federation/mappings".to_string().into() + } + + fn parameters(&self) -> QueryParams<'_> { + let mut params = QueryParams::default(); + params.push_opt("name", self.name.as_ref()); + params.push_opt("domain_id", self.domain_id.as_ref()); + params.push_opt("idp_id", self.idp_id.as_ref()); + params.push_opt("type", self._type.as_ref()); + + params + } + + fn service_type(&self) -> ServiceType { + ServiceType::Identity + } + + fn response_key(&self) -> Option> { + Some("mappings".into()) + } + + /// Returns headers to be set into the request + fn request_headers(&self) -> Option<&HeaderMap> { + self._headers.as_ref() + } + + /// Returns required API version + fn api_version(&self) -> Option { + Some(ApiVersion::new(4, 0)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[cfg(feature = "sync")] + use crate::api::Query; + use crate::test::client::FakeOpenStackClient; + use crate::types::ServiceType; + use http::{HeaderName, HeaderValue}; + use httpmock::MockServer; + use serde_json::json; + + #[test] + fn test_service_type() { + assert_eq!( + Request::builder().build().unwrap().service_type(), + ServiceType::Identity + ); + } + + #[test] + fn test_response_key() { + assert_eq!( + Request::builder().build().unwrap().response_key().unwrap(), + "mappings" + ); + } + + #[cfg(feature = "sync")] + #[test] + fn endpoint() { + let server = MockServer::start(); + let client = FakeOpenStackClient::new(server.base_url()); + let mock = server.mock(|when, then| { + when.method(httpmock::Method::GET) + .path("/federation/mappings".to_string()); + + then.status(200) + .header("content-type", "application/json") + .json_body(json!({ "mappings": {} })); + }); + + let endpoint = Request::builder().build().unwrap(); + let _: serde_json::Value = endpoint.query(&client).unwrap(); + mock.assert(); + } + + #[cfg(feature = "sync")] + #[test] + fn endpoint_headers() { + let server = MockServer::start(); + let client = FakeOpenStackClient::new(server.base_url()); + let mock = server.mock(|when, then| { + when.method(httpmock::Method::GET) + .path("/federation/mappings".to_string()) + .header("foo", "bar") + .header("not_foo", "not_bar"); + then.status(200) + .header("content-type", "application/json") + .json_body(json!({ "mappings": {} })); + }); + + let endpoint = Request::builder() + .headers( + [( + Some(HeaderName::from_static("foo")), + HeaderValue::from_static("bar"), + )] + .into_iter(), + ) + .header( + HeaderName::from_static("not_foo"), + HeaderValue::from_static("not_bar"), + ) + .build() + .unwrap(); + let _: serde_json::Value = endpoint.query(&client).unwrap(); + mock.assert(); + } +} diff --git a/openstack_sdk/src/api/identity/v4/federation/mapping/set.rs b/openstack_sdk/src/api/identity/v4/federation/mapping/set.rs new file mode 100644 index 000000000..07761d989 --- /dev/null +++ b/openstack_sdk/src/api/identity/v4/federation/mapping/set.rs @@ -0,0 +1,327 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +//! TODO: describe domain_id update rules +//! +use derive_builder::Builder; +use http::{HeaderMap, HeaderName, HeaderValue}; + +use crate::api::rest_endpoint_prelude::*; + +use serde::Deserialize; +use serde::Serialize; +use serde_json::Value; +use std::borrow::Cow; +use std::collections::BTreeMap; + +#[derive(Debug, Deserialize, Clone, Serialize)] +pub enum Type { + #[serde(rename = "jwt")] + Jwt, + #[serde(rename = "oidc")] + Oidc, +} + +/// OIDC/JWT attribute mapping update data. +#[derive(Builder, Debug, Deserialize, Clone, Serialize)] +#[builder(setter(strip_option))] +pub struct Mapping<'a> { + /// List of allowed redirect urls (only for `oidc` type). + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) allowed_redirect_uris: Option>>, + + /// List of audiences that must be present in the token. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) bound_audiences: Option>>, + + /// Additional claims that must be present in the token. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, private, setter(into, name = "_bound_claims"))] + pub(crate) bound_claims: Option, Value>>, + + /// Token subject value that must be set in the token. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) bound_subject: Option>>, + + /// `domain_id` owning the attribute mapping. + /// + /// Unset `domain_id` means the attribute mapping is shared and can be used + /// by different domains. This requires `domain_id_claim` to be present. + /// Attribute mapping can be only shared when the referred identity + /// provider is also shared (does not set the `domain_id` attribute). + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) domain_id: Option>>, + + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) domain_id_claim: Option>>, + + /// `groups` claim name. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) groups_claim: Option>>, + + /// ID of the federated identity provider for which this attribute mapping + /// can be used. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) idp_id: Option>>, + + /// Attribute mapping name for federated logins. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) name: Option>>, + + /// List of OIDC scopes. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) oidc_scopes: Option>>, + + /// Fixed project_id for the token. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) token_project_id: Option>>, + + /// List of fixed roles that would be included in the token. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) token_role_ids: Option>>, + + /// Fixed user_id for which the keystone token would be issued. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) token_user_id: Option>>, + + /// Attribute mapping type. + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + #[builder(default)] + pub(crate) _type: Option, + + /// `user_id` claim name. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) user_id_claim: Option>>, + + /// `user_name` claim name. + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(default, setter(into))] + pub(crate) user_name_claim: Option>>, +} + +impl<'a> MappingBuilder<'a> { + /// Additional claims that must be present in the token. + pub fn bound_claims(&mut self, iter: I) -> &mut Self + where + I: Iterator, + K: Into>, + V: Into, + { + self.bound_claims + .get_or_insert(None) + .get_or_insert_with(BTreeMap::new) + .extend(iter.map(|(k, v)| (k.into(), v.into()))); + self + } +} + +#[derive(Builder, Debug, Clone)] +#[builder(setter(strip_option))] +pub struct Request<'a> { + /// OIDC/JWT attribute mapping update data. + #[builder(setter(into))] + pub(crate) mapping: Mapping<'a>, + + /// The ID of the attribute mapping. + #[builder(default, setter(into))] + id: Cow<'a, str>, + + #[builder(setter(name = "_headers"), default, private)] + _headers: Option, +} +impl<'a> Request<'a> { + /// Create a builder for the endpoint. + pub fn builder() -> RequestBuilder<'a> { + RequestBuilder::default() + } +} + +impl<'a> RequestBuilder<'a> { + /// Add a single header to the Mapping. + pub fn header(&mut self, header_name: K, header_value: V) -> &mut Self + where + K: Into, + V: Into, + { + self._headers + .get_or_insert(None) + .get_or_insert_with(HeaderMap::new) + .insert(header_name.into(), header_value.into()); + self + } + + /// Add multiple headers. + pub fn headers(&mut self, iter: I) -> &mut Self + where + I: Iterator, + T: Into<(Option, HeaderValue)>, + { + self._headers + .get_or_insert(None) + .get_or_insert_with(HeaderMap::new) + .extend(iter.map(Into::into)); + self + } +} + +impl RestEndpoint for Request<'_> { + fn method(&self) -> http::Method { + http::Method::PUT + } + + fn endpoint(&self) -> Cow<'static, str> { + format!("federation/mappings/{id}", id = self.id.as_ref(),).into() + } + + fn parameters(&self) -> QueryParams<'_> { + QueryParams::default() + } + + fn body(&self) -> Result)>, BodyError> { + let mut params = JsonBodyParams::default(); + + params.push("mapping", serde_json::to_value(&self.mapping)?); + + params.into_body() + } + + fn service_type(&self) -> ServiceType { + ServiceType::Identity + } + + fn response_key(&self) -> Option> { + Some("mapping".into()) + } + + /// Returns headers to be set into the request + fn request_headers(&self) -> Option<&HeaderMap> { + self._headers.as_ref() + } + + /// Returns required API version + fn api_version(&self) -> Option { + Some(ApiVersion::new(4, 0)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[cfg(feature = "sync")] + use crate::api::Query; + use crate::test::client::FakeOpenStackClient; + use crate::types::ServiceType; + use http::{HeaderName, HeaderValue}; + use httpmock::MockServer; + use serde_json::json; + + #[test] + fn test_service_type() { + assert_eq!( + Request::builder() + .mapping(MappingBuilder::default().build().unwrap()) + .build() + .unwrap() + .service_type(), + ServiceType::Identity + ); + } + + #[test] + fn test_response_key() { + assert_eq!( + Request::builder() + .mapping(MappingBuilder::default().build().unwrap()) + .build() + .unwrap() + .response_key() + .unwrap(), + "mapping" + ); + } + + #[cfg(feature = "sync")] + #[test] + fn endpoint() { + let server = MockServer::start(); + let client = FakeOpenStackClient::new(server.base_url()); + let mock = server.mock(|when, then| { + when.method(httpmock::Method::PUT) + .path(format!("/federation/mappings/{id}", id = "id",)); + + then.status(200) + .header("content-type", "application/json") + .json_body(json!({ "mapping": {} })); + }); + + let endpoint = Request::builder() + .id("id") + .mapping(MappingBuilder::default().build().unwrap()) + .build() + .unwrap(); + let _: serde_json::Value = endpoint.query(&client).unwrap(); + mock.assert(); + } + + #[cfg(feature = "sync")] + #[test] + fn endpoint_headers() { + let server = MockServer::start(); + let client = FakeOpenStackClient::new(server.base_url()); + let mock = server.mock(|when, then| { + when.method(httpmock::Method::PUT) + .path(format!("/federation/mappings/{id}", id = "id",)) + .header("foo", "bar") + .header("not_foo", "not_bar"); + then.status(200) + .header("content-type", "application/json") + .json_body(json!({ "mapping": {} })); + }); + + let endpoint = Request::builder() + .id("id") + .mapping(MappingBuilder::default().build().unwrap()) + .headers( + [( + Some(HeaderName::from_static("foo")), + HeaderValue::from_static("bar"), + )] + .into_iter(), + ) + .header( + HeaderName::from_static("not_foo"), + HeaderValue::from_static("not_bar"), + ) + .build() + .unwrap(); + let _: serde_json::Value = endpoint.query(&client).unwrap(); + mock.assert(); + } +} diff --git a/openstack_types/src/identity/v4/federation.rs b/openstack_types/src/identity/v4/federation.rs index 58204622c..9d3d9f353 100644 --- a/openstack_types/src/identity/v4/federation.rs +++ b/openstack_types/src/identity/v4/federation.rs @@ -17,3 +17,4 @@ //! `identity/v4/federation/identity_provider` REST operations of identity pub mod identity_provider; +pub mod mapping; diff --git a/openstack_types/src/identity/v4/federation/mapping.rs b/openstack_types/src/identity/v4/federation/mapping.rs new file mode 100644 index 000000000..4c08ee417 --- /dev/null +++ b/openstack_types/src/identity/v4/federation/mapping.rs @@ -0,0 +1,19 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +//! `response` REST operations of identity +pub mod response; diff --git a/openstack_types/src/identity/v4/federation/mapping/response.rs b/openstack_types/src/identity/v4/federation/mapping/response.rs new file mode 100644 index 000000000..47be25f13 --- /dev/null +++ b/openstack_types/src/identity/v4/federation/mapping/response.rs @@ -0,0 +1,22 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. + +//! `response` REST operations of identity +pub mod create; +pub mod get; +pub mod list; +pub mod set; diff --git a/openstack_types/src/identity/v4/federation/mapping/response/create.rs b/openstack_types/src/identity/v4/federation/mapping/response/create.rs new file mode 100644 index 000000000..33545cf04 --- /dev/null +++ b/openstack_types/src/identity/v4/federation/mapping/response/create.rs @@ -0,0 +1,134 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. +//! Response type for the POST `federation/mappings` operation + +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::collections::BTreeMap; +use structable::{StructTable, StructTableOptions}; + +/// Mapping response representation +#[derive(Clone, Deserialize, Serialize, StructTable)] +pub struct MappingResponse { + /// List of allowed redirect urls (only for `oidc` type). + #[serde(default)] + #[structable(optional, serialize)] + pub allowed_redirect_uris: Option>, + + /// List of audiences that must be present in the token. + #[serde(default)] + #[structable(optional, serialize)] + pub bound_audiences: Option>, + + /// Additional claims that must be present in the token. + #[serde(default)] + #[structable(optional, serialize)] + pub bound_claims: Option>, + + /// Token subject value that must be set in the token. + #[serde(default)] + #[structable(optional)] + pub bound_subject: Option, + + /// `domain_id` owning the attribute mapping. + /// + /// Unset `domain_id` means the attribute mapping is shared and can be used + /// by different domains. This requires `domain_id_claim` to be present. + /// Attribute mapping can be only shared when the referred identity + /// provider is also shared (does not set the `domain_id` attribute). + #[serde(default)] + #[structable(optional)] + pub domain_id: Option, + + /// `domain_id` claim name. + #[serde(default)] + #[structable(optional)] + pub domain_id_claim: Option, + + /// `groups` claim name. + #[serde(default)] + #[structable(optional)] + pub groups_claim: Option, + + /// Attribute mapping ID for federated logins. + #[structable()] + pub id: String, + + /// ID of the federated identity provider for which this attribute mapping + /// can be used. + #[structable()] + pub idp_id: String, + + /// Attribute mapping name for federated logins. + #[structable()] + pub name: String, + + /// List of OIDC scopes. + #[serde(default)] + #[structable(optional, serialize)] + pub oidc_scopes: Option>, + + /// Fixed project_id for the token. + #[serde(default)] + #[structable(optional)] + pub token_project_id: Option, + + /// List of fixed roles that would be included in the token. + #[serde(default)] + #[structable(optional, serialize)] + pub token_role_ids: Option>, + + /// Fixed user_id for which the keystone token would be issued. + #[serde(default)] + #[structable(optional)] + pub token_user_id: Option, + + /// Attribute mapping type. + #[serde(rename = "type")] + #[structable(serialize, title = "type")] + pub _type: Type, + + /// `user_id` claim name. + #[structable()] + pub user_id_claim: String, + + /// `user_name` claim name. + #[structable()] + pub user_name_claim: String, +} + +#[derive(Debug, Deserialize, Clone, Serialize)] +pub enum Type { + // Jwt + #[serde(rename = "jwt")] + Jwt, + + // Oidc + #[serde(rename = "oidc")] + Oidc, +} + +impl std::str::FromStr for Type { + type Err = (); + fn from_str(input: &str) -> Result { + match input { + "jwt" => Ok(Self::Jwt), + "oidc" => Ok(Self::Oidc), + _ => Err(()), + } + } +} diff --git a/openstack_types/src/identity/v4/federation/mapping/response/get.rs b/openstack_types/src/identity/v4/federation/mapping/response/get.rs new file mode 100644 index 000000000..f532c0a6f --- /dev/null +++ b/openstack_types/src/identity/v4/federation/mapping/response/get.rs @@ -0,0 +1,134 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. +//! Response type for the GET `federation/mappings/{id}` operation + +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::collections::BTreeMap; +use structable::{StructTable, StructTableOptions}; + +/// Mapping response representation +#[derive(Clone, Deserialize, Serialize, StructTable)] +pub struct MappingResponse { + /// List of allowed redirect urls (only for `oidc` type). + #[serde(default)] + #[structable(optional, serialize)] + pub allowed_redirect_uris: Option>, + + /// List of audiences that must be present in the token. + #[serde(default)] + #[structable(optional, serialize)] + pub bound_audiences: Option>, + + /// Additional claims that must be present in the token. + #[serde(default)] + #[structable(optional, serialize)] + pub bound_claims: Option>, + + /// Token subject value that must be set in the token. + #[serde(default)] + #[structable(optional)] + pub bound_subject: Option, + + /// `domain_id` owning the attribute mapping. + /// + /// Unset `domain_id` means the attribute mapping is shared and can be used + /// by different domains. This requires `domain_id_claim` to be present. + /// Attribute mapping can be only shared when the referred identity + /// provider is also shared (does not set the `domain_id` attribute). + #[serde(default)] + #[structable(optional)] + pub domain_id: Option, + + /// `domain_id` claim name. + #[serde(default)] + #[structable(optional)] + pub domain_id_claim: Option, + + /// `groups` claim name. + #[serde(default)] + #[structable(optional)] + pub groups_claim: Option, + + /// Attribute mapping ID for federated logins. + #[structable()] + pub id: String, + + /// ID of the federated identity provider for which this attribute mapping + /// can be used. + #[structable()] + pub idp_id: String, + + /// Attribute mapping name for federated logins. + #[structable()] + pub name: String, + + /// List of OIDC scopes. + #[serde(default)] + #[structable(optional, serialize)] + pub oidc_scopes: Option>, + + /// Fixed project_id for the token. + #[serde(default)] + #[structable(optional)] + pub token_project_id: Option, + + /// List of fixed roles that would be included in the token. + #[serde(default)] + #[structable(optional, serialize)] + pub token_role_ids: Option>, + + /// Fixed user_id for which the keystone token would be issued. + #[serde(default)] + #[structable(optional)] + pub token_user_id: Option, + + /// Attribute mapping type. + #[serde(rename = "type")] + #[structable(serialize, title = "type")] + pub _type: Type, + + /// `user_id` claim name. + #[structable()] + pub user_id_claim: String, + + /// `user_name` claim name. + #[structable()] + pub user_name_claim: String, +} + +#[derive(Debug, Deserialize, Clone, Serialize)] +pub enum Type { + // Jwt + #[serde(rename = "jwt")] + Jwt, + + // Oidc + #[serde(rename = "oidc")] + Oidc, +} + +impl std::str::FromStr for Type { + type Err = (); + fn from_str(input: &str) -> Result { + match input { + "jwt" => Ok(Self::Jwt), + "oidc" => Ok(Self::Oidc), + _ => Err(()), + } + } +} diff --git a/openstack_types/src/identity/v4/federation/mapping/response/list.rs b/openstack_types/src/identity/v4/federation/mapping/response/list.rs new file mode 100644 index 000000000..c72ccc28d --- /dev/null +++ b/openstack_types/src/identity/v4/federation/mapping/response/list.rs @@ -0,0 +1,134 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. +//! Response type for the GET `federation/mappings` operation + +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::collections::BTreeMap; +use structable::{StructTable, StructTableOptions}; + +/// Mapping response representation +#[derive(Clone, Deserialize, Serialize, StructTable)] +pub struct MappingResponse { + /// List of allowed redirect urls (only for `oidc` type). + #[serde(default)] + #[structable(optional, serialize, wide)] + pub allowed_redirect_uris: Option>, + + /// List of audiences that must be present in the token. + #[serde(default)] + #[structable(optional, serialize, wide)] + pub bound_audiences: Option>, + + /// Additional claims that must be present in the token. + #[serde(default)] + #[structable(optional, serialize, wide)] + pub bound_claims: Option>, + + /// Token subject value that must be set in the token. + #[serde(default)] + #[structable(optional, wide)] + pub bound_subject: Option, + + /// `domain_id` owning the attribute mapping. + /// + /// Unset `domain_id` means the attribute mapping is shared and can be used + /// by different domains. This requires `domain_id_claim` to be present. + /// Attribute mapping can be only shared when the referred identity + /// provider is also shared (does not set the `domain_id` attribute). + #[serde(default)] + #[structable(optional, wide)] + pub domain_id: Option, + + /// `domain_id` claim name. + #[serde(default)] + #[structable(optional, wide)] + pub domain_id_claim: Option, + + /// `groups` claim name. + #[serde(default)] + #[structable(optional, wide)] + pub groups_claim: Option, + + /// Attribute mapping ID for federated logins. + #[structable()] + pub id: String, + + /// ID of the federated identity provider for which this attribute mapping + /// can be used. + #[structable(wide)] + pub idp_id: String, + + /// Attribute mapping name for federated logins. + #[structable()] + pub name: String, + + /// List of OIDC scopes. + #[serde(default)] + #[structable(optional, serialize, wide)] + pub oidc_scopes: Option>, + + /// Fixed project_id for the token. + #[serde(default)] + #[structable(optional, wide)] + pub token_project_id: Option, + + /// List of fixed roles that would be included in the token. + #[serde(default)] + #[structable(optional, serialize, wide)] + pub token_role_ids: Option>, + + /// Fixed user_id for which the keystone token would be issued. + #[serde(default)] + #[structable(optional, wide)] + pub token_user_id: Option, + + /// Attribute mapping type. + #[serde(rename = "type")] + #[structable(serialize, title = "type", wide)] + pub _type: Type, + + /// `user_id` claim name. + #[structable(wide)] + pub user_id_claim: String, + + /// `user_name` claim name. + #[structable(wide)] + pub user_name_claim: String, +} + +#[derive(Debug, Deserialize, Clone, Serialize)] +pub enum Type { + // Jwt + #[serde(rename = "jwt")] + Jwt, + + // Oidc + #[serde(rename = "oidc")] + Oidc, +} + +impl std::str::FromStr for Type { + type Err = (); + fn from_str(input: &str) -> Result { + match input { + "jwt" => Ok(Self::Jwt), + "oidc" => Ok(Self::Oidc), + _ => Err(()), + } + } +} diff --git a/openstack_types/src/identity/v4/federation/mapping/response/set.rs b/openstack_types/src/identity/v4/federation/mapping/response/set.rs new file mode 100644 index 000000000..206c89e0a --- /dev/null +++ b/openstack_types/src/identity/v4/federation/mapping/response/set.rs @@ -0,0 +1,134 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// WARNING: This file is automatically generated from OpenAPI schema using +// `openstack-codegenerator`. +//! Response type for the PUT `federation/mappings/{id}` operation + +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::collections::BTreeMap; +use structable::{StructTable, StructTableOptions}; + +/// Mapping response representation +#[derive(Clone, Deserialize, Serialize, StructTable)] +pub struct MappingResponse { + /// List of allowed redirect urls (only for `oidc` type). + #[serde(default)] + #[structable(optional, serialize)] + pub allowed_redirect_uris: Option>, + + /// List of audiences that must be present in the token. + #[serde(default)] + #[structable(optional, serialize)] + pub bound_audiences: Option>, + + /// Additional claims that must be present in the token. + #[serde(default)] + #[structable(optional, serialize)] + pub bound_claims: Option>, + + /// Token subject value that must be set in the token. + #[serde(default)] + #[structable(optional)] + pub bound_subject: Option, + + /// `domain_id` owning the attribute mapping. + /// + /// Unset `domain_id` means the attribute mapping is shared and can be used + /// by different domains. This requires `domain_id_claim` to be present. + /// Attribute mapping can be only shared when the referred identity + /// provider is also shared (does not set the `domain_id` attribute). + #[serde(default)] + #[structable(optional)] + pub domain_id: Option, + + /// `domain_id` claim name. + #[serde(default)] + #[structable(optional)] + pub domain_id_claim: Option, + + /// `groups` claim name. + #[serde(default)] + #[structable(optional)] + pub groups_claim: Option, + + /// Attribute mapping ID for federated logins. + #[structable()] + pub id: String, + + /// ID of the federated identity provider for which this attribute mapping + /// can be used. + #[structable()] + pub idp_id: String, + + /// Attribute mapping name for federated logins. + #[structable()] + pub name: String, + + /// List of OIDC scopes. + #[serde(default)] + #[structable(optional, serialize)] + pub oidc_scopes: Option>, + + /// Fixed project_id for the token. + #[serde(default)] + #[structable(optional)] + pub token_project_id: Option, + + /// List of fixed roles that would be included in the token. + #[serde(default)] + #[structable(optional, serialize)] + pub token_role_ids: Option>, + + /// Fixed user_id for which the keystone token would be issued. + #[serde(default)] + #[structable(optional)] + pub token_user_id: Option, + + /// Attribute mapping type. + #[serde(rename = "type")] + #[structable(serialize, title = "type")] + pub _type: Type, + + /// `user_id` claim name. + #[structable()] + pub user_id_claim: String, + + /// `user_name` claim name. + #[structable()] + pub user_name_claim: String, +} + +#[derive(Debug, Deserialize, Clone, Serialize)] +pub enum Type { + // Jwt + #[serde(rename = "jwt")] + Jwt, + + // Oidc + #[serde(rename = "oidc")] + Oidc, +} + +impl std::str::FromStr for Type { + type Err = (); + fn from_str(input: &str) -> Result { + match input { + "jwt" => Ok(Self::Jwt), + "oidc" => Ok(Self::Oidc), + _ => Err(()), + } + } +}