From 4579f75b642f5eef756c6079fcc5cba56462a364 Mon Sep 17 00:00:00 2001 From: Artem Goncharov Date: Wed, 25 Mar 2026 11:59:20 +0100 Subject: [PATCH] refactor: Split the core-types crate Bring the compilation time to around 1m by splitting the core crate into core-types and core. Reverse the dependency by making api-types depend on the core-types (what is more logical) but making this dependency behind the gate feature (conv - conversion). --- Cargo.lock | 41 ++ Cargo.toml | 7 +- Dockerfile | 11 +- crates/api-types/Cargo.toml | 8 + crates/api-types/src/catalog_conv.rs | 29 ++ crates/api-types/src/error.rs | 160 +++++++- .../error.rs => api-types/src/error_conv.rs} | 223 +++------- crates/api-types/src/federation.rs | 34 +- .../src/federation/identity_provider_conv.rs} | 39 +- .../src/federation/mapping_conv.rs} | 55 +-- crates/api-types/src/k8s_auth.rs | 46 +++ .../src/k8s_auth/auth_conv.rs} | 21 +- crates/api-types/src/k8s_auth/instance.rs | 2 +- .../src/k8s_auth/instance_conv.rs} | 40 +- .../src/k8s_auth/role_conv.rs} | 59 +-- crates/api-types/src/lib.rs | 6 + crates/api-types/src/scope_conv.rs | 95 +++++ crates/api-types/src/trust.rs | 19 + .../src/trust/trust_conv.rs} | 13 +- crates/api-types/src/v3.rs | 13 + crates/api-types/src/v3/auth_conv.rs | 64 +++ .../src/v3/group_conv.rs} | 34 +- .../src/v3/project_conv.rs} | 14 +- .../src/v3/role_assignment_conv.rs} | 78 ++-- .../role.rs => api-types/src/v3/role_conv.rs} | 38 +- .../user.rs => api-types/src/v3/user_conv.rs} | 52 +-- crates/api-types/src/v4.rs | 3 + .../src/v4/token_restriction_conv.rs} | 43 +- crates/appcred-sql/Cargo.toml | 1 + .../appcred-sql/src/application_credential.rs | 4 +- .../src/application_credential/create.rs | 11 +- .../src/application_credential/get.rs | 4 +- .../src/application_credential/list.rs | 2 +- crates/appcred-sql/src/lib.rs | 2 +- crates/assignment-sql/Cargo.toml | 1 + crates/assignment-sql/src/assignment.rs | 17 +- crates/assignment-sql/src/assignment/check.rs | 6 +- .../assignment-sql/src/assignment/create.rs | 6 +- .../assignment-sql/src/assignment/delete.rs | 6 +- crates/assignment-sql/src/assignment/list.rs | 10 +- crates/assignment-sql/src/lib.rs | 11 +- crates/catalog-sql/Cargo.toml | 1 + crates/catalog-sql/src/endpoint.rs | 6 +- crates/catalog-sql/src/endpoint/get.rs | 3 +- crates/catalog-sql/src/endpoint/list.rs | 6 +- crates/catalog-sql/src/lib.rs | 2 +- crates/catalog-sql/src/service.rs | 6 +- crates/catalog-sql/src/service/get.rs | 3 +- crates/catalog-sql/src/service/list.rs | 6 +- crates/core-types/Cargo.toml | 30 ++ .../src/application_credential.rs} | 8 +- .../application_credential}/access_rule.rs | 0 .../application_credential.rs | 2 +- .../src/application_credential/error.rs | 100 +++++ .../api.rs => core-types/src/assignment.rs} | 9 +- .../src/assignment}/assignment.rs | 17 - crates/core-types/src/assignment/error.rs | 99 +++++ .../auth/mod.rs => core-types/src/auth.rs} | 21 +- crates/core-types/src/catalog.rs | 21 + .../src/catalog}/endpoint.rs | 0 crates/core-types/src/catalog/error.rs | 49 +++ .../src/catalog}/service.rs | 0 crates/core-types/src/error.rs | 190 +++++++++ crates/core-types/src/federation.rs | 23 ++ .../src/federation}/auth_state.rs | 2 +- crates/core-types/src/federation/error.rs | 67 +++ .../src/federation}/identity_provider.rs | 0 .../src/federation}/mapping.rs | 0 .../src/federation/types.rs | 0 .../types.rs => core-types/src/identity.rs} | 12 +- crates/core-types/src/identity/error.rs | 138 +++++++ .../src/identity}/group.rs | 0 .../src/identity}/service_account.rs | 0 .../types => core-types/src/identity}/user.rs | 46 +-- .../src/identity_mapping.rs} | 8 +- .../core-types/src/identity_mapping/error.rs | 57 +++ .../src/identity_mapping}/id_mapping.rs | 0 crates/core-types/src/k8s_auth.rs | 24 ++ .../types => core-types/src/k8s_auth}/auth.rs | 9 - crates/core-types/src/k8s_auth/error.rs | 195 +++++++++ .../src/k8s_auth}/instance.rs | 0 .../types => core-types/src/k8s_auth}/role.rs | 0 .../api/types.rs => core-types/src/lib.rs} | 20 +- .../types.rs => core-types/src/resource.rs} | 12 +- .../src/resource}/domain.rs | 0 crates/core-types/src/resource/error.rs | 62 +++ .../src/resource}/project.rs | 0 crates/core-types/src/revoke.rs | 19 + crates/core-types/src/revoke/error.rs | 44 ++ .../src/revoke}/revocation_event.rs | 26 +- .../api/types.rs => core-types/src/role.rs} | 8 +- crates/core-types/src/role/error.rs | 58 +++ .../types => core-types/src/role}/role.rs | 0 .../types.rs => core-types/src/scope.rs} | 2 +- .../types.rs => core-types/src/token.rs} | 226 +---------- crates/core-types/src/token/error.rs | 182 +++++++++ .../src/token/payload.rs} | 27 +- .../token/payload}/application_credential.rs | 12 +- .../src/token/payload}/common.rs | 0 .../src/token/payload}/domain_scoped.rs | 10 +- .../payload}/federation_domain_scoped.rs | 10 +- .../payload}/federation_project_scoped.rs | 10 +- .../src/token/payload}/federation_unscoped.rs | 6 +- .../src/token/payload}/project_scoped.rs | 10 +- .../src/token/payload/restricted.rs | 96 +++++ .../src/token/payload}/system_scoped.rs | 8 +- .../src/token/payload}/trust.rs | 9 +- .../src/token/payload}/unscoped.rs | 6 +- .../src/token/restriction.rs} | 78 +--- .../types.rs => core-types/src/trust.rs} | 9 +- crates/core-types/src/trust/error.rs | 97 +++++ .../types => core-types/src/trust}/trust.rs | 2 +- crates/core/Cargo.toml | 9 +- crates/core/README.md | 112 ----- crates/core/src/api.rs | 6 +- crates/core/src/api/common.rs | 30 +- crates/core/src/api/types.rs | 112 ----- crates/core/src/api/v3.rs | 5 - crates/core/src/api/v3/auth.rs | 46 --- crates/core/src/api/v3/auth/token/common.rs | 38 -- .../core/src/api/v3/auth/token/token_impl.rs | 374 +++++++++-------- crates/core/src/api/v4.rs | 1 - crates/core/src/api/v4/auth.rs | 46 --- crates/core/src/api/v4/auth/token/common.rs | 41 -- .../core/src/api/v4/auth/token/token_impl.rs | 381 +++++++++--------- .../src/application_credential/backend.rs | 3 +- .../core/src/application_credential/error.rs | 76 +--- .../core/src/application_credential/mock.rs | 6 +- crates/core/src/application_credential/mod.rs | 10 +- .../{types => }/provider_api.rs | 2 +- .../src/application_credential/service.rs | 10 +- crates/core/src/assignment/backend.rs | 3 +- crates/core/src/assignment/error.rs | 85 +--- crates/core/src/assignment/mock.rs | 6 +- crates/core/src/assignment/mod.rs | 10 +- .../assignment/{types => }/provider_api.rs | 2 +- crates/core/src/assignment/service.rs | 19 +- .../src/{k8s_auth/api/types.rs => auth.rs} | 5 +- crates/core/src/catalog/backend.rs | 3 +- crates/core/src/catalog/error.rs | 37 +- crates/core/src/catalog/mock.rs | 3 +- crates/core/src/catalog/mod.rs | 7 +- .../src/catalog/{types => }/provider_api.rs | 5 +- crates/core/src/catalog/service.rs | 3 +- crates/core/src/common.rs | 1 - crates/core/src/error.rs | 201 +-------- crates/core/src/federation/api.rs | 102 ----- crates/core/src/federation/api/error.rs | 33 -- crates/core/src/federation/backend.rs | 3 +- crates/core/src/federation/error.rs | 54 +-- crates/core/src/federation/mock.rs | 5 +- crates/core/src/federation/mod.rs | 8 +- .../{types/provider.rs => provider_api.rs} | 3 +- crates/core/src/federation/service.rs | 3 +- crates/core/src/identity/backend.rs | 3 +- crates/core/src/identity/error.rs | 106 +---- crates/core/src/identity/mock.rs | 4 +- crates/core/src/identity/mod.rs | 51 ++- .../src/identity/{types => }/provider_api.rs | 4 +- crates/core/src/identity/service.rs | 6 +- crates/core/src/identity_mapping/backend.rs | 4 +- crates/core/src/identity_mapping/error.rs | 45 +-- crates/core/src/identity_mapping/mock.rs | 4 +- crates/core/src/identity_mapping/mod.rs | 6 +- .../{types => }/provider_api.rs | 3 +- crates/core/src/identity_mapping/service.rs | 3 +- crates/core/src/k8s_auth/api.rs | 15 - crates/core/src/k8s_auth/api/error.rs | 59 --- crates/core/src/k8s_auth/auth.rs | 54 ++- crates/core/src/k8s_auth/backend.rs | 4 +- crates/core/src/k8s_auth/error.rs | 200 ++------- crates/core/src/k8s_auth/mock.rs | 6 +- crates/core/src/k8s_auth/mod.rs | 11 +- .../src/k8s_auth/{types => }/provider_api.rs | 6 +- crates/core/src/k8s_auth/service.rs | 5 +- crates/core/src/k8s_auth/types.rs | 17 +- crates/core/src/policy.rs | 7 + crates/core/src/resource/backend.rs | 3 +- crates/core/src/resource/error.rs | 50 +-- crates/core/src/resource/mock.rs | 5 +- crates/core/src/resource/mod.rs | 10 +- .../src/resource/{types => }/provider_api.rs | 4 +- crates/core/src/resource/service.rs | 3 +- crates/core/src/resource/types.rs | 21 - crates/core/src/revoke/backend.rs | 6 +- crates/core/src/revoke/error.rs | 23 +- crates/core/src/revoke/mock.rs | 5 +- crates/core/src/revoke/mod.rs | 8 +- .../src/revoke/{types => }/provider_api.rs | 6 +- crates/core/src/revoke/service.rs | 5 +- crates/core/src/revoke/types.rs | 21 - crates/core/src/role/backend.rs | 4 +- crates/core/src/role/error.rs | 45 +-- crates/core/src/role/mock.rs | 4 +- crates/core/src/role/mod.rs | 11 +- .../core/src/role/{types => }/provider_api.rs | 3 +- crates/core/src/role/service.rs | 3 +- crates/core/src/role/types.rs | 4 +- crates/core/src/token/backend.rs | 3 +- crates/core/src/token/error.rs | 161 +------- crates/core/src/token/mock.rs | 7 +- crates/core/src/token/mod.rs | 6 +- .../src/token/{types => }/provider_api.rs | 4 +- crates/core/src/token/service.rs | 51 ++- crates/core/src/token/validate.rs | 213 ++++++++++ crates/core/src/trust/api/error.rs | 29 -- crates/core/src/trust/backend.rs | 4 +- crates/core/src/trust/error.rs | 82 +--- crates/core/src/trust/mock.rs | 4 +- crates/core/src/trust/mod.rs | 8 +- .../{types/provider.rs => provider_api.rs} | 4 +- crates/core/src/trust/service.rs | 17 +- crates/federation-sql/Cargo.toml | 1 + crates/federation-sql/src/auth_state.rs | 4 +- .../federation-sql/src/auth_state/create.rs | 3 +- crates/federation-sql/src/auth_state/get.rs | 3 +- .../federation-sql/src/identity_provider.rs | 2 +- .../src/identity_provider/create.rs | 6 +- .../src/identity_provider/get.rs | 3 +- .../src/identity_provider/list.rs | 6 +- .../src/identity_provider/update.rs | 6 +- crates/federation-sql/src/lib.rs | 5 +- crates/federation-sql/src/mapping.rs | 2 +- crates/federation-sql/src/mapping/create.rs | 5 +- crates/federation-sql/src/mapping/get.rs | 3 +- crates/federation-sql/src/mapping/list.rs | 8 +- crates/federation-sql/src/mapping/update.rs | 8 +- crates/identity-sql/Cargo.toml | 1 + crates/identity-sql/src/authenticate.rs | 13 +- crates/identity-sql/src/federated_user.rs | 2 +- crates/identity-sql/src/group.rs | 2 +- crates/identity-sql/src/group/create.rs | 6 +- crates/identity-sql/src/group/get.rs | 3 +- crates/identity-sql/src/group/list.rs | 8 +- crates/identity-sql/src/lib.rs | 2 +- crates/identity-sql/src/local_user.rs | 2 +- crates/identity-sql/src/local_user/create.rs | 3 +- crates/identity-sql/src/nonlocal_user.rs | 2 +- crates/identity-sql/src/password.rs | 3 +- .../src/service_account/create.rs | 5 +- .../identity-sql/src/service_account/get.rs | 8 +- crates/identity-sql/src/user.rs | 2 +- crates/identity-sql/src/user/create.rs | 16 +- crates/identity-sql/src/user/get.rs | 6 +- crates/identity-sql/src/user/list.rs | 6 +- crates/identity-sql/src/user_group/list.rs | 3 +- crates/identity-sql/src/user_option.rs | 5 +- crates/identity-sql/src/user_option/create.rs | 3 +- crates/identity-sql/src/user_option/list.rs | 3 +- crates/idmapping-sql/Cargo.toml | 1 + crates/idmapping-sql/src/id_mapping.rs | 2 +- crates/idmapping-sql/src/id_mapping/get.rs | 3 +- crates/idmapping-sql/src/lib.rs | 2 +- crates/k8s-auth-sql/Cargo.toml | 1 + crates/k8s-auth-sql/src/instance.rs | 4 +- crates/k8s-auth-sql/src/instance/create.rs | 6 +- crates/k8s-auth-sql/src/instance/get.rs | 3 +- crates/k8s-auth-sql/src/instance/list.rs | 6 +- crates/k8s-auth-sql/src/instance/update.rs | 6 +- crates/k8s-auth-sql/src/lib.rs | 2 +- crates/k8s-auth-sql/src/role.rs | 4 +- crates/k8s-auth-sql/src/role/create.rs | 6 +- crates/k8s-auth-sql/src/role/get.rs | 3 +- crates/k8s-auth-sql/src/role/list.rs | 6 +- crates/k8s-auth-sql/src/role/update.rs | 6 +- crates/keystone/Cargo.toml | 5 +- crates/keystone/src/api/common.rs | 11 +- crates/keystone/src/api/error.rs | 2 +- crates/keystone/src/api/mod.rs | 2 +- crates/keystone/src/api/types.rs | 116 ------ .../keystone/src/api/v3/auth/project/list.rs | 22 +- .../keystone/src/api/v3/auth/token/common.rs | 6 +- .../keystone/src/api/v3/auth/token/create.rs | 19 +- crates/keystone/src/api/v3/auth/token/show.rs | 11 +- crates/keystone/src/api/v3/group/mod.rs | 45 ++- crates/keystone/src/api/v3/project/create.rs | 4 +- crates/keystone/src/api/v3/project/delete.rs | 4 +- crates/keystone/src/api/v3/role/create.rs | 7 +- crates/keystone/src/api/v3/role/list.rs | 14 +- crates/keystone/src/api/v3/role/show.rs | 39 +- .../src/api/v3/role_assignment/list.rs | 9 +- .../project/user/role/check.rs | 23 +- .../project/user/role/grant.rs | 20 +- .../project/user/role/revoke.rs | 16 +- crates/keystone/src/api/v3/user/mod.rs | 48 ++- crates/keystone/src/api/v4/group/mod.rs | 8 +- .../keystone/src/api/v4/token/restriction.rs | 3 +- .../src/api/v4/token/restriction/create.rs | 13 +- .../src/api/v4/token/restriction/delete.rs | 6 +- .../src/api/v4/token/restriction/list.rs | 11 +- .../src/api/v4/token/restriction/show.rs | 15 +- .../src/api/v4/token/restriction/update.rs | 12 +- crates/keystone/src/api/v4/user/mod.rs | 42 +- crates/keystone/src/federation/api/auth.rs | 4 +- crates/keystone/src/federation/api/common.rs | 8 +- .../api/identity_provider/create.rs | 13 +- .../api/identity_provider/delete.rs | 8 +- .../federation/api/identity_provider/list.rs | 17 +- .../federation/api/identity_provider/show.rs | 15 +- .../api/identity_provider/update.rs | 14 +- crates/keystone/src/federation/api/jwt.rs | 31 +- .../src/federation/api/mapping/create.rs | 13 +- .../src/federation/api/mapping/delete.rs | 4 +- .../src/federation/api/mapping/list.rs | 4 +- .../src/federation/api/mapping/show.rs | 14 +- .../src/federation/api/mapping/update.rs | 13 +- crates/keystone/src/federation/api/oidc.rs | 9 +- crates/keystone/src/federation/api/types.rs | 9 +- .../keystone/src/federation/api/types/auth.rs | 18 - .../federation/api/types/identity_provider.rs | 11 +- .../src/federation/api/types/mapping.rs | 12 +- crates/keystone/src/k8s_auth/api/auth.rs | 17 +- crates/keystone/src/k8s_auth/api/error.rs | 59 --- .../src/k8s_auth/api/instance/create.rs | 28 +- .../src/k8s_auth/api/instance/delete.rs | 4 +- .../src/k8s_auth/api/instance/list.rs | 9 +- .../src/k8s_auth/api/instance/show.rs | 18 +- .../src/k8s_auth/api/instance/update.rs | 18 +- .../keystone/src/k8s_auth/api/role/create.rs | 28 +- .../keystone/src/k8s_auth/api/role/delete.rs | 4 +- crates/keystone/src/k8s_auth/api/role/list.rs | 11 +- crates/keystone/src/k8s_auth/api/role/show.rs | 29 +- .../keystone/src/k8s_auth/api/role/update.rs | 32 +- crates/resource-sql/Cargo.toml | 1 + crates/resource-sql/src/domain.rs | 6 +- crates/resource-sql/src/domain/create.rs | 6 +- crates/resource-sql/src/domain/get.rs | 3 +- crates/resource-sql/src/domain/list.rs | 6 +- crates/resource-sql/src/lib.rs | 5 +- crates/resource-sql/src/project.rs | 6 +- crates/resource-sql/src/project/create.rs | 6 +- crates/resource-sql/src/project/get.rs | 3 +- crates/resource-sql/src/project/list.rs | 6 +- crates/resource-sql/src/project/tree.rs | 5 +- crates/revoke-sql/Cargo.toml | 1 + crates/revoke-sql/src/create.rs | 2 +- crates/revoke-sql/src/lib.rs | 5 +- crates/revoke-sql/src/list.rs | 4 +- crates/role-sql/Cargo.toml | 1 + crates/role-sql/src/lib.rs | 2 +- crates/role-sql/src/role.rs | 6 +- crates/role-sql/src/role/create.rs | 6 +- crates/role-sql/src/role/get.rs | 5 +- crates/role-sql/src/role/list.rs | 8 +- crates/token-fernet/Cargo.toml | 1 + .../src/application_credential.rs | 2 +- crates/token-fernet/src/domain_scoped.rs | 2 +- .../src/federation_domain_scoped.rs | 2 +- .../src/federation_project_scoped.rs | 2 +- .../token-fernet/src/federation_unscoped.rs | 2 +- crates/token-fernet/src/lib.rs | 14 +- crates/token-fernet/src/project_scoped.rs | 2 +- crates/token-fernet/src/restricted.rs | 2 +- crates/token-fernet/src/system_scoped.rs | 2 +- crates/token-fernet/src/trust.rs | 2 +- crates/token-fernet/src/unscoped.rs | 2 +- crates/token-restriction-sql/Cargo.toml | 1 + crates/token-restriction-sql/src/create.rs | 2 +- crates/token-restriction-sql/src/get.rs | 2 +- crates/token-restriction-sql/src/lib.rs | 2 +- crates/token-restriction-sql/src/list.rs | 2 +- crates/token-restriction-sql/src/update.rs | 2 +- crates/trust-sql/Cargo.toml | 1 + crates/trust-sql/src/lib.rs | 3 +- crates/trust-sql/src/trust.rs | 8 +- crates/trust-sql/src/trust/get.rs | 5 +- crates/trust-sql/src/trust/list.rs | 8 +- crates/webauthn/Cargo.toml | 3 +- crates/webauthn/src/api/auth/finish.rs | 5 +- crates/webauthn/src/api/auth/start.rs | 2 +- crates/webauthn/src/api/register/finish.rs | 2 +- tests/federation/src/dex.rs | 2 +- tests/federation/src/github.rs | 2 +- tests/federation/src/keycloak.rs | 2 +- tests/federation/src/keystone_utils.rs | 2 +- tests/integration/Cargo.toml | 1 + .../integration/src/application_credential.rs | 4 +- .../src/application_credential/create.rs | 4 +- .../src/application_credential/get.rs | 4 +- .../src/application_credential/list.rs | 2 +- tests/integration/src/assignment.rs | 3 +- .../integration/src/assignment/grant/list.rs | 3 +- .../src/assignment/grant/revoke.rs | 12 +- tests/integration/src/common.rs | 6 +- tests/integration/src/identity.rs | 3 +- .../src/identity/service_account/create.rs | 3 +- .../src/identity/service_account/get.rs | 3 +- tests/integration/src/identity/user/create.rs | 3 +- tests/integration/src/identity/user/get.rs | 3 +- tests/integration/src/identity/user/list.rs | 3 +- tests/integration/src/identity/user_group.rs | 2 +- tests/integration/src/k8s_auth/instance.rs | 3 +- .../src/k8s_auth/instance/create.rs | 3 +- .../src/k8s_auth/instance/delete.rs | 3 +- .../integration/src/k8s_auth/instance/get.rs | 3 +- .../integration/src/k8s_auth/instance/list.rs | 3 +- .../src/k8s_auth/instance/update.rs | 3 +- tests/integration/src/k8s_auth/role.rs | 3 +- tests/integration/src/k8s_auth/role/create.rs | 3 +- tests/integration/src/k8s_auth/role/delete.rs | 3 +- tests/integration/src/k8s_auth/role/get.rs | 3 +- tests/integration/src/k8s_auth/role/list.rs | 3 +- tests/integration/src/k8s_auth/role/update.rs | 3 +- tests/integration/src/resource.rs | 3 +- tests/integration/src/revoke.rs | 13 +- tests/integration/src/role.rs | 3 +- tests/integration/src/role/create.rs | 3 +- tests/integration/src/role/list.rs | 3 +- .../src/token/token_restriction.rs | 3 +- tests/integration/src/token/validate.rs | 6 +- .../token/validate/application_credential.rs | 6 +- tests/integration/src/token/validate/trust.rs | 5 +- tools/Dockerfile.functest | 8 +- 413 files changed, 4270 insertions(+), 4205 deletions(-) create mode 100644 crates/api-types/src/catalog_conv.rs rename crates/{core/src/api/error.rs => api-types/src/error_conv.rs} (65%) rename crates/{core/src/federation/api/types/identity_provider.rs => api-types/src/federation/identity_provider_conv.rs} (72%) rename crates/{core/src/federation/api/types/mapping.rs => api-types/src/federation/mapping_conv.rs} (71%) rename crates/{core/src/k8s_auth/api/types/auth.rs => api-types/src/k8s_auth/auth_conv.rs} (60%) rename crates/{core/src/k8s_auth/api/types/instance.rs => api-types/src/k8s_auth/instance_conv.rs} (59%) rename crates/{core/src/k8s_auth/api/types/role.rs => api-types/src/k8s_auth/role_conv.rs} (51%) create mode 100644 crates/api-types/src/scope_conv.rs rename crates/{core/src/trust/api/types/trust.rs => api-types/src/trust/trust_conv.rs} (76%) create mode 100644 crates/api-types/src/v3/auth_conv.rs rename crates/{core/src/api/v3/group.rs => api-types/src/v3/group_conv.rs} (61%) rename crates/{core/src/api/v3/project.rs => api-types/src/v3/project_conv.rs} (80%) rename crates/{core/src/api/v3/role_assignment.rs => api-types/src/v3/role_assignment_conv.rs} (64%) rename crates/{core/src/api/v3/role.rs => api-types/src/v3/role_conv.rs} (62%) rename crates/{core/src/api/v3/user.rs => api-types/src/v3/user_conv.rs} (73%) rename crates/{core/src/api/v4/token_restriction.rs => api-types/src/v4/token_restriction_conv.rs} (63%) create mode 100644 crates/core-types/Cargo.toml rename crates/{core/src/application_credential/types.rs => core-types/src/application_credential.rs} (88%) rename crates/{core/src/application_credential/types => core-types/src/application_credential}/access_rule.rs (100%) rename crates/{core/src/application_credential/types => core-types/src/application_credential}/application_credential.rs (99%) create mode 100644 crates/core-types/src/application_credential/error.rs rename crates/{core/src/trust/api.rs => core-types/src/assignment.rs} (86%) rename crates/{core/src/assignment/types => core-types/src/assignment}/assignment.rs (93%) create mode 100644 crates/core-types/src/assignment/error.rs rename crates/{core/src/auth/mod.rs => core-types/src/auth.rs} (95%) create mode 100644 crates/core-types/src/catalog.rs rename crates/{core/src/catalog/types => core-types/src/catalog}/endpoint.rs (100%) create mode 100644 crates/core-types/src/catalog/error.rs rename crates/{core/src/catalog/types => core-types/src/catalog}/service.rs (100%) create mode 100644 crates/core-types/src/error.rs create mode 100644 crates/core-types/src/federation.rs rename crates/{core/src/federation/types => core-types/src/federation}/auth_state.rs (97%) create mode 100644 crates/core-types/src/federation/error.rs rename crates/{core/src/federation/types => core-types/src/federation}/identity_provider.rs (100%) rename crates/{core/src/federation/types => core-types/src/federation}/mapping.rs (100%) rename crates/{core => core-types}/src/federation/types.rs (100%) rename crates/{core/src/identity/types.rs => core-types/src/identity.rs} (85%) create mode 100644 crates/core-types/src/identity/error.rs rename crates/{core/src/identity/types => core-types/src/identity}/group.rs (100%) rename crates/{core/src/identity/types => core-types/src/identity}/service_account.rs (100%) rename crates/{core/src/identity/types => core-types/src/identity}/user.rs (87%) rename crates/{core/src/identity_mapping/types.rs => core-types/src/identity_mapping.rs} (88%) create mode 100644 crates/core-types/src/identity_mapping/error.rs rename crates/{core/src/identity_mapping/types => core-types/src/identity_mapping}/id_mapping.rs (100%) create mode 100644 crates/core-types/src/k8s_auth.rs rename crates/{core/src/k8s_auth/types => core-types/src/k8s_auth}/auth.rs (82%) create mode 100644 crates/core-types/src/k8s_auth/error.rs rename crates/{core/src/k8s_auth/types => core-types/src/k8s_auth}/instance.rs (100%) rename crates/{core/src/k8s_auth/types => core-types/src/k8s_auth}/role.rs (100%) rename crates/{core/src/trust/api/types.rs => core-types/src/lib.rs} (63%) rename crates/{core/src/assignment/types.rs => core-types/src/resource.rs} (83%) rename crates/{core/src/resource/types => core-types/src/resource}/domain.rs (100%) create mode 100644 crates/core-types/src/resource/error.rs rename crates/{core/src/resource/types => core-types/src/resource}/project.rs (100%) create mode 100644 crates/core-types/src/revoke.rs create mode 100644 crates/core-types/src/revoke/error.rs rename crates/{core/src/revoke/types => core-types/src/revoke}/revocation_event.rs (95%) rename crates/{core/src/federation/api/types.rs => core-types/src/role.rs} (87%) create mode 100644 crates/core-types/src/role/error.rs rename crates/{core/src/role/types => core-types/src/role}/role.rs (100%) rename crates/{core/src/common/types.rs => core-types/src/scope.rs} (98%) rename crates/{core/src/token/types.rs => core-types/src/token.rs} (56%) create mode 100644 crates/core-types/src/token/error.rs rename crates/{core/src/trust/types.rs => core-types/src/token/payload.rs} (55%) rename crates/{core/src/token/types => core-types/src/token/payload}/application_credential.rs (91%) rename crates/{core/src/token/types => core-types/src/token/payload}/common.rs (100%) rename crates/{core/src/token/types => core-types/src/token/payload}/domain_scoped.rs (92%) rename crates/{core/src/token/types => core-types/src/token/payload}/federation_domain_scoped.rs (93%) rename crates/{core/src/token/types => core-types/src/token/payload}/federation_project_scoped.rs (93%) rename crates/{core/src/token/types => core-types/src/token/payload}/federation_unscoped.rs (95%) rename crates/{core/src/token/types => core-types/src/token/payload}/project_scoped.rs (92%) create mode 100644 crates/core-types/src/token/payload/restricted.rs rename crates/{core/src/token/types => core-types/src/token/payload}/system_scoped.rs (94%) rename crates/{core/src/token/types => core-types/src/token/payload}/trust.rs (94%) rename crates/{core/src/token/types => core-types/src/token/payload}/unscoped.rs (95%) rename crates/{core/src/token/types/restricted.rs => core-types/src/token/restriction.rs} (59%) rename crates/{core/src/catalog/types.rs => core-types/src/trust.rs} (87%) create mode 100644 crates/core-types/src/trust/error.rs rename crates/{core/src/trust/types => core-types/src/trust}/trust.rs (99%) delete mode 100644 crates/core/README.md delete mode 100644 crates/core/src/api/types.rs delete mode 100644 crates/core/src/api/v3/auth/token/common.rs delete mode 100644 crates/core/src/api/v4/auth/token/common.rs rename crates/core/src/application_credential/{types => }/provider_api.rs (96%) rename crates/core/src/assignment/{types => }/provider_api.rs (97%) rename crates/core/src/{k8s_auth/api/types.rs => auth.rs} (92%) rename crates/core/src/catalog/{types => }/provider_api.rs (96%) delete mode 100644 crates/core/src/federation/api.rs delete mode 100644 crates/core/src/federation/api/error.rs rename crates/core/src/federation/{types/provider.rs => provider_api.rs} (98%) rename crates/core/src/identity/{types => }/provider_api.rs (98%) rename crates/core/src/identity_mapping/{types => }/provider_api.rs (95%) delete mode 100644 crates/core/src/k8s_auth/api.rs delete mode 100644 crates/core/src/k8s_auth/api/error.rs rename crates/core/src/k8s_auth/{types => }/provider_api.rs (95%) rename crates/core/src/resource/{types => }/provider_api.rs (97%) delete mode 100644 crates/core/src/resource/types.rs rename crates/core/src/revoke/{types => }/provider_api.rs (92%) delete mode 100644 crates/core/src/revoke/types.rs rename crates/core/src/role/{types => }/provider_api.rs (97%) rename crates/core/src/token/{types => }/provider_api.rs (98%) create mode 100644 crates/core/src/token/validate.rs delete mode 100644 crates/core/src/trust/api/error.rs rename crates/core/src/trust/{types/provider.rs => provider_api.rs} (94%) delete mode 100644 crates/keystone/src/federation/api/types/auth.rs delete mode 100644 crates/keystone/src/k8s_auth/api/error.rs diff --git a/Cargo.lock b/Cargo.lock index c058cc56..22c2ebf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3301,6 +3301,7 @@ dependencies = [ "openstack-keystone-catalog-sql", "openstack-keystone-config", "openstack-keystone-core", + "openstack-keystone-core-types", "openstack-keystone-distributed-storage", "openstack-keystone-federation-sql", "openstack-keystone-identity-sql", @@ -3342,15 +3343,21 @@ dependencies = [ name = "openstack-keystone-api-types" version = "0.1.0" dependencies = [ + "axum", "base64 0.22.1", "chrono", "derive_builder", + "eyre", "http", + "openstack-keystone-core-types", "secrecy", "serde", "serde_json", + "serde_urlencoded", "thiserror 2.0.18", + "url", "utoipa", + "uuid", "validator", "webauthn-rs-proto", ] @@ -3363,6 +3370,7 @@ dependencies = [ "chrono", "openstack-keystone-config", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "secrecy", "tokio", @@ -3377,6 +3385,7 @@ dependencies = [ "async-trait", "openstack-keystone-config", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "tokio", "tracing", @@ -3388,6 +3397,7 @@ version = "0.1.0" dependencies = [ "async-trait", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "serde_json", "tokio", @@ -3425,6 +3435,7 @@ dependencies = [ "mockall", "openstack-keystone-api-types", "openstack-keystone-config", + "openstack-keystone-core-types", "rand 0.10.0", "reqwest 0.13.2", "rstest", @@ -3443,6 +3454,24 @@ dependencies = [ "validator", ] +[[package]] +name = "openstack-keystone-core-types" +version = "0.1.1" +dependencies = [ + "base64 0.22.1", + "chrono", + "derive_builder", + "eyre", + "secrecy", + "serde", + "serde_json", + "thiserror 2.0.18", + "tracing", + "url", + "uuid", + "validator", +] + [[package]] name = "openstack-keystone-distributed-storage" version = "0.1.0" @@ -3475,6 +3504,7 @@ dependencies = [ "chrono", "derive_builder", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "serde_json", "tokio", @@ -3491,6 +3521,7 @@ dependencies = [ "derive_builder", "openstack-keystone-config", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "serde", "serde_json", @@ -3507,6 +3538,7 @@ dependencies = [ "async-trait", "chrono", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "tokio", "tracing", @@ -3518,6 +3550,7 @@ version = "0.1.0" dependencies = [ "async-trait", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "tokio", "tracing", @@ -3530,6 +3563,7 @@ version = "0.1.0" dependencies = [ "async-trait", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "serde_json", "tokio", @@ -3544,6 +3578,7 @@ dependencies = [ "async-trait", "chrono", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "serde_json", "tokio", @@ -3556,6 +3591,7 @@ version = "0.1.0" dependencies = [ "async-trait", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "serde_json", "tokio", @@ -3579,6 +3615,7 @@ dependencies = [ "nix", "openstack-keystone-config", "openstack-keystone-core", + "openstack-keystone-core-types", "rmp", "scopeguard", "secrecy", @@ -3596,6 +3633,7 @@ version = "0.1.0" dependencies = [ "async-trait", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "tokio", "tracing", @@ -3608,6 +3646,7 @@ dependencies = [ "async-trait", "chrono", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "serde_json", "tokio", @@ -3628,6 +3667,7 @@ dependencies = [ "mockall", "openstack-keystone-api-types", "openstack-keystone-core", + "openstack-keystone-core-types", "sea-orm", "serde", "serde_json", @@ -5973,6 +6013,7 @@ dependencies = [ "openstack-keystone-assignment-sql", "openstack-keystone-config", "openstack-keystone-core", + "openstack-keystone-core-types", "openstack-keystone-federation-sql", "openstack-keystone-identity-sql", "openstack-keystone-k8s-auth-sql", diff --git a/Cargo.toml b/Cargo.toml index 041022b0..6dfbe14f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,9 @@ members = [ "crates/catalog-sql", "crates/config", "crates/core", + "crates/core-types", "crates/federation-sql", + "crates/identity-sql", "crates/idmapping-sql", "crates/k8s-auth-sql", "crates/keystone", @@ -14,12 +16,13 @@ members = [ "crates/role-sql", "crates/storage", "crates/token-fernet", + "crates/token-restriction-sql", "crates/trust-sql", "crates/revoke-sql", "crates/webauthn", "tests/api", "tests/integration", - "tests/federation", "crates/token-restriction-sql", "crates/identity-sql", + "tests/federation", ] exclude = [ "tests/loadtest" @@ -87,7 +90,7 @@ serde_json = { version = "1.0" } serde_urlencoded = { version = "0.7" } tempfile = { version = "3.27" } thiserror = { version = "2.0" } -tokio = { version = "1.50" } +tokio = { version = "1.50", default-features = false } tokio-util = { version = "0.7" } tonic = { version = "0.14" } tonic-prost-build = { version = "0.14" } diff --git a/Dockerfile b/Dockerfile index 443eab4f..99a1bdb0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,6 +15,10 @@ RUN USER=root cargo new keystone WORKDIR /usr/src/keystone +RUN USER=root cargo new --name core --lib crates/core +RUN USER=root cargo new --name core-types --lib crates/core-types +RUN USER=root cargo new --name api-types --lib crates/api-types + RUN USER=root cargo new --name appcred-sql --lib crates/appcred-sql RUN USER=root cargo new --name assignment-sql --lib crates/assignment-sql RUN USER=root cargo new --name catalog-sql --lib crates/catalog-sql @@ -35,6 +39,7 @@ COPY crates/appcred-sql/Cargo.toml /usr/src/keystone/crates/appcred-sql/ COPY crates/assignment-sql/Cargo.toml /usr/src/keystone/crates/assignment-sql/ COPY crates/config/Cargo.toml /usr/src/keystone/crates/config/ COPY crates/core/Cargo.toml /usr/src/keystone/crates/core/ +COPY crates/core-types/Cargo.toml /usr/src/keystone/crates/core-types/ COPY crates/catalog-sql/Cargo.toml /usr/src/keystone/crates/catalog-sql/ COPY crates/federation-sql/Cargo.toml /usr/src/keystone/crates/federation-sql/ COPY crates/identity-sql/Cargo.toml /usr/src/keystone/crates/identity-sql/ @@ -58,17 +63,12 @@ RUN mkdir -p crates/keystone/src/bin && touch crates/keystone/src/lib.rs &&\ cp src/main.rs crates/keystone/src/bin/keystone_db.rs &&\ mkdir -p tests/loadtest/src &&\ cp src/main.rs tests/loadtest/src/main.rs &&\ - mkdir -p crates/api-types/src && touch crates/api-types/src/lib.rs &&\ mkdir -p crates/config/src && touch crates/config/src/lib.rs &&\ - mkdir -p crates/core/src && touch crates/core/src/lib.rs &&\ mkdir -p crates/storage/src && touch crates/storage/src/lib.rs &&\ mkdir -p crates/token-fernet/src && touch crates/token-fernet/src/lib.rs &&\ mkdir -p crates/token-fernet/benches && touch crates/token-fernet/benches/fernet_token.rs &&\ mkdir -p crates/webauthn/src && touch crates/webauthn/src/lib.rs -# Set the working directory -#WORKDIR /usr/src/keystone - ## This is a dummy build to get the dependencies cached. #RUN cargo build --target x86_64-unknown-linux-musl --release RUN cargo build -p openstack-keystone --release @@ -77,6 +77,7 @@ RUN cargo build -p openstack-keystone --release COPY crates/keystone/ /usr/src/keystone/crates/keystone COPY crates/config/ /usr/src/keystone/crates/config COPY crates/core/ /usr/src/keystone/crates/core +COPY crates/core-types/ /usr/src/keystone/crates/core-types COPY crates/api-types/ /usr/src/keystone/crates/api-types COPY crates/storage/ /usr/src/keystone/crates/storage COPY crates/token-fernet/ /usr/src/keystone/crates/token-fernet diff --git a/crates/api-types/Cargo.toml b/crates/api-types/Cargo.toml index 61d49ab6..66ec1528 100644 --- a/crates/api-types/Cargo.toml +++ b/crates/api-types/Cargo.toml @@ -13,16 +13,24 @@ default = [] builder = ["dep:derive_builder"] openapi = ["dep:utoipa"] validate = ["dep:validator"] +conv = ["dep:axum", "dep:openstack-keystone-core-types", "dep:uuid", "builder", "dep:serde_urlencoded", "dep:url", "dep:validator"] [dependencies] +axum = { workspace = true, features = ["json"], optional = true } base64.workspace = true chrono = { workspace = true, features = ["serde"] } derive_builder = { workspace = true, optional = true } +eyre.workspace = true http = { workspace = true, optional = true } +openstack-keystone-core-types = { version = "0.1", path = "../core-types/", optional = true } secrecy = { workspace = true, features = ["serde"] } serde.workspace = true serde_json.workspace = true +serde_urlencoded = { workspace = true, optional = true } thiserror.workspace = true utoipa = { workspace = true, features = ["chrono"], optional = true } validator = { workspace = true, features = ["derive"], optional = true } webauthn-rs-proto.workspace = true +url = { workspace = true, optional = true } +uuid = { workspace = true, features = ["v4"], optional = true } + diff --git a/crates/api-types/src/catalog_conv.rs b/crates/api-types/src/catalog_conv.rs new file mode 100644 index 00000000..5962383d --- /dev/null +++ b/crates/api-types/src/catalog_conv.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 +//! Keystone API types. +use openstack_keystone_core_types::catalog as provider_types; + +use crate::catalog as api_types; + +impl From for api_types::Endpoint { + fn from(value: provider_types::Endpoint) -> Self { + Self { + id: value.id.clone(), + interface: value.interface.clone(), + url: value.url.clone(), + region: value.region_id.clone(), + region_id: value.region_id.clone(), + } + } +} diff --git a/crates/api-types/src/error.rs b/crates/api-types/src/error.rs index c49fd638..5b522729 100644 --- a/crates/api-types/src/error.rs +++ b/crates/api-types/src/error.rs @@ -14,29 +14,151 @@ //! # Keystone API types Error use thiserror::Error; -/// Builder error. -/// -/// A wrapper error that is used instead of the error generated by the -/// `derive_builder`. +#[cfg(feature = "builder")] +pub use openstack_keystone_core_types::error::BuilderError; + +/// Keystone API operation errors. #[derive(Debug, Error)] -pub enum BuilderError { - /// Uninitialized field. - #[error("{0}")] - UninitializedField(String), - /// Custom validation error. - #[error("{0}")] - Validation(String), +pub enum KeystoneApiError { + /// Selected authentication is forbidden. + #[error("changing current authentication scope is forbidden")] + AuthenticationRescopeForbidden, + + #[error("Attempted to authenticate with an unsupported method.")] + AuthMethodNotSupported, + + #[error("{0}.")] + BadRequest(String), + + /// Base64 decoding error. + #[error(transparent)] + Base64Decode(#[from] base64::DecodeError), + + #[error("conflict, resource already existing")] + Conflict(String), + + #[error("domain id or name must be present")] + DomainIdOrName, + + #[error("You are not authorized to perform the requested action.")] + Forbidden { + /// The source of the error. + #[source] + source: Box, + }, + + #[error("invalid header header")] + InvalidHeader, + + #[error("invalid token")] + InvalidToken, + + #[error("internal server error: {0}")] + InternalError(String), + + #[error("could not find {resource}: {identifier}")] + NotFound { + resource: String, + identifier: String, + }, + + /// Others. + #[error(transparent)] + Other(#[from] eyre::Report), + + #[error("project id or name must be present")] + ProjectIdOrName, + + #[error("project domain must be present")] + ProjectDomain, + + /// Selected authentication is forbidden. + #[error("selected authentication is forbidden")] + SelectedAuthenticationForbidden, + + /// (de)serialization error. + #[error(transparent)] + Serde { + #[from] + source: serde_json::Error, + }, + + #[error("missing x-subject-token header")] + SubjectTokenMissing, + + #[error("The request you have made requires authentication.")] + UnauthorizedNoContext, + + #[error("{}", .context.clone().unwrap_or("The request you have made requires authentication.".to_string()))] + Unauthorized { + context: Option, + /// The source of the error. + #[source] + source: Box, + }, } -impl From for BuilderError { - fn from(s: String) -> Self { - Self::Validation(s) +impl KeystoneApiError { + pub fn forbidden(error: E) -> Self + where + E: std::error::Error + Send + Sync + 'static, + { + Self::Forbidden { + source: Box::new(error), + } } -} -#[cfg(feature = "builder")] -impl From for BuilderError { - fn from(ufe: derive_builder::UninitializedFieldError) -> Self { - Self::UninitializedField(ufe.to_string()) + pub fn internal(error: E) -> Self + where + E: std::error::Error + Send + Sync + 'static, + { + Self::InternalError(error.to_string()) + //{ + // source: Box::new(error), + //} + } + + pub fn unauthorized(error: E, context: Option) -> Self + where + E: std::error::Error + Send + Sync + 'static, + C: Into, + { + Self::Unauthorized { + context: context.map(Into::into), + source: Box::new(error), + } } } + +///// Builder error. +///// +///// A wrapper error that is used instead of the error generated by the +///// `derive_builder`. +//#[derive(Debug, Error)] +//#[non_exhaustive] +//pub enum BuilderError { +// /// Uninitialized field. +// #[error("{0}")] +// UninitializedField(String), +// /// Custom validation error. +// #[error("{0}")] +// Validation(String), +//} +// +//impl From for BuilderError { +// fn from(s: String) -> Self { +// Self::Validation(s) +// } +//} +// +//impl From for BuilderError { +// fn from(ufe: derive_builder::UninitializedFieldError) -> Self { +// Self::UninitializedField(ufe.to_string()) +// } +//} +// +//impl From for KeystoneApiError { +// fn from(value: BuilderError) -> Self { +// Self::InternalError(value.to_string()) +// } +//} diff --git a/crates/core/src/api/error.rs b/crates/api-types/src/error_conv.rs similarity index 65% rename from crates/core/src/api/error.rs rename to crates/api-types/src/error_conv.rs index bb825b9e..31490070 100644 --- a/crates/core/src/api/error.rs +++ b/crates/api-types/src/error_conv.rs @@ -11,162 +11,31 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 -//! # Keystone API error. -use axum::{ - Json, - extract::rejection::JsonRejection, - http::StatusCode, - response::{IntoResponse, Response}, -}; -use serde_json::json; -use thiserror::Error; -use tracing::error; - -use crate::assignment::error::AssignmentProviderError; -use crate::auth::AuthenticationError; -use crate::catalog::error::CatalogProviderError; -use crate::error::BuilderError; -use crate::identity::error::IdentityProviderError; -use crate::policy::PolicyError; -use crate::resource::error::ResourceProviderError; -use crate::revoke::error::RevokeProviderError; -use crate::role::error::RoleProviderError; -use crate::token::error::TokenProviderError; - -/// Keystone API operation errors. -#[derive(Debug, Error)] -pub enum KeystoneApiError { - /// Selected authentication is forbidden. - #[error("changing current authentication scope is forbidden")] - AuthenticationRescopeForbidden, - - #[error("Attempted to authenticate with an unsupported method.")] - AuthMethodNotSupported, - - #[error("{0}.")] - BadRequest(String), - - /// Base64 decoding error. - #[error(transparent)] - Base64Decode(#[from] base64::DecodeError), - #[error("conflict, resource already existing")] - Conflict(String), - - #[error("domain id or name must be present")] - DomainIdOrName, - - #[error("You are not authorized to perform the requested action.")] - Forbidden { - /// The source of the error. - #[source] - source: Box, +use { + axum::{ + Json, + extract::rejection::JsonRejection, + http::StatusCode, + response::{IntoResponse, Response}, }, + serde_json::json, +}; - #[error("invalid header header")] - InvalidHeader, - - #[error("invalid token")] - InvalidToken, - - #[error(transparent)] - JsonExtractorRejection(#[from] JsonRejection), - - #[error("internal server error: {0}")] - InternalError(String), - - #[error("could not find {resource}: {identifier}")] - NotFound { - resource: String, - identifier: String, - }, - - /// Others. - #[error(transparent)] - Other(#[from] eyre::Report), - - #[error(transparent)] - Policy { - #[from] - source: PolicyError, - }, - - #[error("project id or name must be present")] - ProjectIdOrName, - - #[error("project domain must be present")] - ProjectDomain, - - /// Selected authentication is forbidden. - #[error("selected authentication is forbidden")] - SelectedAuthenticationForbidden, - - /// (de)serialization error. - #[error(transparent)] - Serde { - #[from] - source: serde_json::Error, - }, - - #[error("missing x-subject-token header")] - SubjectTokenMissing, - - #[error("The request you have made requires authentication.")] - UnauthorizedNoContext, - - #[error("{}", .context.clone().unwrap_or("The request you have made requires authentication.".to_string()))] - Unauthorized { - context: Option, - /// The source of the error. - #[source] - source: Box, - }, - - /// Request validation error. - #[error("request validation failed: {source}")] - Validator { - /// The source of the error. - #[from] - source: validator::ValidationErrors, - }, -} - -impl KeystoneApiError { - pub fn forbidden(error: E) -> Self - where - E: std::error::Error + Send + Sync + 'static, - { - Self::Forbidden { - source: Box::new(error), - } - } - - pub fn internal(error: E) -> Self - where - E: std::error::Error + Send + Sync + 'static, - { - Self::InternalError(error.to_string()) - //{ - // source: Box::new(error), - //} - } +use openstack_keystone_core_types::assignment::AssignmentProviderError; +use openstack_keystone_core_types::auth::AuthenticationError; +use openstack_keystone_core_types::catalog::CatalogProviderError; +use openstack_keystone_core_types::error::BuilderError; +use openstack_keystone_core_types::identity::IdentityProviderError; +use openstack_keystone_core_types::resource::ResourceProviderError; +use openstack_keystone_core_types::revoke::RevokeProviderError; +use openstack_keystone_core_types::role::RoleProviderError; +use openstack_keystone_core_types::token::TokenProviderError; - pub fn unauthorized(error: E, context: Option) -> Self - where - E: std::error::Error + Send + Sync + 'static, - C: Into, - { - Self::Unauthorized { - context: context.map(Into::into), - source: Box::new(error), - } - } -} +use crate::error::KeystoneApiError; impl IntoResponse for KeystoneApiError { fn into_response(self) -> Response { - error!("Error happened during request processing: {:#?}", self); - let status_code = match self { KeystoneApiError::Conflict(_) => StatusCode::CONFLICT, KeystoneApiError::NotFound { .. } => StatusCode::NOT_FOUND, @@ -174,7 +43,7 @@ impl IntoResponse for KeystoneApiError { KeystoneApiError::Unauthorized { .. } => StatusCode::UNAUTHORIZED, KeystoneApiError::UnauthorizedNoContext => StatusCode::UNAUTHORIZED, KeystoneApiError::Forbidden { .. } => StatusCode::FORBIDDEN, - KeystoneApiError::Policy { .. } => StatusCode::FORBIDDEN, + //KeystoneApiError::Policy { .. } => StatusCode::FORBIDDEN, KeystoneApiError::SelectedAuthenticationForbidden | KeystoneApiError::AuthenticationRescopeForbidden => StatusCode::BAD_REQUEST, KeystoneApiError::InternalError(_) | KeystoneApiError::Other(..) => { @@ -191,6 +60,18 @@ impl IntoResponse for KeystoneApiError { } } +impl From for KeystoneApiError { + fn from(value: BuilderError) -> Self { + Self::InternalError(value.to_string()) + } +} + +impl From for KeystoneApiError { + fn from(value: JsonRejection) -> Self { + Self::BadRequest(value.to_string()) + } +} + impl From for KeystoneApiError { fn from(value: AuthenticationError) -> Self { match value { @@ -260,18 +141,6 @@ impl From for KeystoneApiError { } } -impl From for KeystoneApiError { - fn from(value: crate::error::BuilderError) -> Self { - Self::InternalError(value.to_string()) - } -} - -impl From for KeystoneApiError { - fn from(value: openstack_keystone_api_types::error::BuilderError) -> Self { - Self::InternalError(value.to_string()) - } -} - impl From for KeystoneApiError { fn from(source: RoleProviderError) -> Self { match source { @@ -286,18 +155,6 @@ impl From for KeystoneApiError { } } -impl From for KeystoneApiError { - fn from(value: serde_urlencoded::ser::Error) -> Self { - Self::InternalError(value.to_string()) - } -} - -impl From for KeystoneApiError { - fn from(value: url::ParseError) -> Self { - Self::InternalError(value.to_string()) - } -} - impl From for KeystoneApiError { fn from(value: CatalogProviderError) -> Self { match value { @@ -367,8 +224,26 @@ impl From for KeystoneApiError { } } +impl From for KeystoneApiError { + fn from(value: serde_urlencoded::ser::Error) -> Self { + Self::InternalError(value.to_string()) + } +} + +impl From for KeystoneApiError { + fn from(value: url::ParseError) -> Self { + Self::InternalError(value.to_string()) + } +} + impl From for KeystoneApiError { fn from(value: uuid::Error) -> Self { Self::InternalError(value.to_string()) } } + +impl From for KeystoneApiError { + fn from(value: validator::ValidationErrors) -> Self { + Self::BadRequest(value.to_string()) + } +} diff --git a/crates/api-types/src/federation.rs b/crates/api-types/src/federation.rs index 4545605b..f5d73c1b 100644 --- a/crates/api-types/src/federation.rs +++ b/crates/api-types/src/federation.rs @@ -12,6 +12,34 @@ // // SPDX-License-Identifier: Apache-2.0 //! # Federation API types -pub mod auth; -pub mod identity_provider; -pub mod mapping; +mod auth; +mod identity_provider; +#[cfg(feature = "conv")] +mod identity_provider_conv; +mod mapping; +#[cfg(feature = "conv")] +mod mapping_conv; + +pub use auth::*; +pub use identity_provider::*; +pub use mapping::*; + +#[cfg(feature = "conv")] +use openstack_keystone_core_types::federation::FederationProviderError; +#[cfg(feature = "conv")] +impl From for crate::error::KeystoneApiError { + fn from(source: FederationProviderError) -> Self { + match source { + FederationProviderError::IdentityProviderNotFound(x) => Self::NotFound { + resource: "identity provider".into(), + identifier: x, + }, + FederationProviderError::MappingNotFound(x) => Self::NotFound { + resource: "mapping provider".into(), + identifier: x, + }, + FederationProviderError::Conflict(x) => Self::Conflict(x), + other => Self::InternalError(other.to_string()), + } + } +} diff --git a/crates/core/src/federation/api/types/identity_provider.rs b/crates/api-types/src/federation/identity_provider_conv.rs similarity index 72% rename from crates/core/src/federation/api/types/identity_provider.rs rename to crates/api-types/src/federation/identity_provider_conv.rs index 4e8105db..26421936 100644 --- a/crates/core/src/federation/api/types/identity_provider.rs +++ b/crates/api-types/src/federation/identity_provider_conv.rs @@ -12,18 +12,13 @@ // // SPDX-License-Identifier: Apache-2.0 //! Federated identity provider types. -use axum::{ - Json, - http::StatusCode, - response::{IntoResponse, Response}, -}; -use openstack_keystone_api_types::federation::identity_provider as api_identity_provider; +use openstack_keystone_core_types::federation as provider_types; -use crate::federation::types; +use crate::federation::identity_provider as api_types; -impl From for api_identity_provider::IdentityProvider { - fn from(value: types::IdentityProvider) -> Self { +impl From for api_types::IdentityProvider { + fn from(value: provider_types::IdentityProvider) -> Self { Self { id: value.id, name: value.name, @@ -42,8 +37,8 @@ impl From for api_identity_provider::IdentityProvider { } } -impl From for types::IdentityProviderCreate { - fn from(value: api_identity_provider::IdentityProviderCreateRequest) -> Self { +impl From for provider_types::IdentityProviderCreate { + fn from(value: api_types::IdentityProviderCreateRequest) -> Self { Self { id: None, name: value.identity_provider.name, @@ -63,8 +58,8 @@ impl From for types::Ident } } -impl From for types::IdentityProviderUpdate { - fn from(value: api_identity_provider::IdentityProviderUpdateRequest) -> Self { +impl From for provider_types::IdentityProviderUpdate { + fn from(value: api_types::IdentityProviderUpdateRequest) -> Self { Self { name: value.identity_provider.name, enabled: value.identity_provider.enabled, @@ -82,22 +77,10 @@ impl From for types::Ident } } -impl IntoResponse for types::IdentityProvider { - fn into_response(self) -> Response { - ( - StatusCode::OK, - Json(api_identity_provider::IdentityProviderResponse { - identity_provider: api_identity_provider::IdentityProvider::from(self), - }), - ) - .into_response() - } -} - -impl From - for types::IdentityProviderListParameters +impl From + for provider_types::IdentityProviderListParameters { - fn from(value: api_identity_provider::IdentityProviderListParameters) -> Self { + fn from(value: api_types::IdentityProviderListParameters) -> Self { Self { name: value.name, domain_ids: None, //value.domain_id, diff --git a/crates/core/src/federation/api/types/mapping.rs b/crates/api-types/src/federation/mapping_conv.rs similarity index 71% rename from crates/core/src/federation/api/types/mapping.rs rename to crates/api-types/src/federation/mapping_conv.rs index e1219357..22eab0b5 100644 --- a/crates/core/src/federation/api/types/mapping.rs +++ b/crates/api-types/src/federation/mapping_conv.rs @@ -12,20 +12,15 @@ // // SPDX-License-Identifier: Apache-2.0 //! Federated attribute mapping types. -use axum::{ - Json, - http::StatusCode, - response::{IntoResponse, Response}, -}; use uuid::Uuid; -use openstack_keystone_api_types::federation::mapping as api_mapping; +use openstack_keystone_core_types::federation as provider_types; -use crate::api::KeystoneApiError; -use crate::federation::types; +use crate::error::KeystoneApiError; +use crate::federation::mapping as api_types; -impl From for api_mapping::Mapping { - fn from(value: types::Mapping) -> Self { +impl From for api_types::Mapping { + fn from(value: provider_types::Mapping) -> Self { Self { id: value.id, name: value.name, @@ -48,8 +43,8 @@ impl From for api_mapping::Mapping { } } -impl From for types::Mapping { - fn from(value: api_mapping::MappingCreateRequest) -> Self { +impl From for provider_types::Mapping { + fn from(value: api_types::MappingCreateRequest) -> Self { Self { id: value.mapping.id.unwrap_or_else(|| Uuid::new_v4().into()), name: value.mapping.name, @@ -72,8 +67,8 @@ impl From for types::Mapping { } } -impl From for types::MappingUpdate { - fn from(value: api_mapping::MappingUpdateRequest) -> Self { +impl From for provider_types::MappingUpdate { + fn from(value: api_types::MappingUpdateRequest) -> Self { Self { name: value.mapping.name, idp_id: value.mapping.idp_id, @@ -94,40 +89,28 @@ impl From for types::MappingUpdate { } } -impl IntoResponse for types::Mapping { - fn into_response(self) -> Response { - ( - StatusCode::OK, - Json(api_mapping::MappingResponse { - mapping: api_mapping::Mapping::from(self), - }), - ) - .into_response() - } -} - -impl From for api_mapping::MappingType { - fn from(value: types::MappingType) -> Self { +impl From for api_types::MappingType { + fn from(value: provider_types::MappingType) -> Self { match value { - types::MappingType::Oidc => Self::Oidc, - types::MappingType::Jwt => Self::Jwt, + provider_types::MappingType::Oidc => Self::Oidc, + provider_types::MappingType::Jwt => Self::Jwt, } } } -impl From for types::MappingType { - fn from(value: api_mapping::MappingType) -> Self { +impl From for provider_types::MappingType { + fn from(value: api_types::MappingType) -> Self { match value { - api_mapping::MappingType::Oidc => Self::Oidc, - api_mapping::MappingType::Jwt => Self::Jwt, + api_types::MappingType::Oidc => Self::Oidc, + api_types::MappingType::Jwt => Self::Jwt, } } } -impl TryFrom for types::MappingListParameters { +impl TryFrom for provider_types::MappingListParameters { type Error = KeystoneApiError; - fn try_from(value: api_mapping::MappingListParameters) -> Result { + fn try_from(value: api_types::MappingListParameters) -> Result { Ok(Self { domain_id: value.domain_id, idp_id: value.idp_id, diff --git a/crates/api-types/src/k8s_auth.rs b/crates/api-types/src/k8s_auth.rs index 7a34b658..7e5cc5e5 100644 --- a/crates/api-types/src/k8s_auth.rs +++ b/crates/api-types/src/k8s_auth.rs @@ -20,3 +20,49 @@ pub mod role; pub use auth::*; pub use instance::*; pub use role::*; + +#[cfg(feature = "conv")] +mod auth_conv; +#[cfg(feature = "conv")] +mod instance_conv; +#[cfg(feature = "conv")] +mod role_conv; + +#[cfg(feature = "conv")] +use openstack_keystone_core_types::k8s_auth::K8sAuthProviderError; +#[cfg(feature = "conv")] +impl From for crate::error::KeystoneApiError { + fn from(source: K8sAuthProviderError) -> Self { + match source { + K8sAuthProviderError::AudienceMismatch => Self::forbidden(source), + K8sAuthProviderError::CaCertificateUnknown => Self::forbidden(source), + K8sAuthProviderError::AuthInstanceNotActive(..) => Self::forbidden(source), + K8sAuthProviderError::AuthInstanceNotFound(x) => Self::NotFound { + resource: "k8s auth configuration".into(), + identifier: x, + }, + K8sAuthProviderError::Conflict(x) => Self::Conflict(x), + K8sAuthProviderError::FailedBoundServiceAccountName(..) => Self::forbidden(source), + K8sAuthProviderError::FailedBoundServiceAccountNamespace(..) => Self::forbidden(source), + K8sAuthProviderError::Jwt { .. } => Self::forbidden(source), + K8sAuthProviderError::ExpiredToken => Self::forbidden(source), + K8sAuthProviderError::InsecureAlgorithm => Self::forbidden(source), + K8sAuthProviderError::InvalidToken => Self::forbidden(source), + K8sAuthProviderError::RoleNotFound(x) => Self::NotFound { + resource: "k8s auth role".into(), + identifier: x, + }, + K8sAuthProviderError::RoleNotActive(..) => Self::forbidden(source), + K8sAuthProviderError::RoleInstanceOwnershipMismatch(..) => Self::forbidden(source), + K8sAuthProviderError::TokenRestrictionNotFound(x) => Self::NotFound { + resource: "token restriction".into(), + identifier: x, + }, + K8sAuthProviderError::UserNotFound(x) => Self::NotFound { + resource: "user/service account".into(), + identifier: x, + }, + other => Self::InternalError(other.to_string()), + } + } +} diff --git a/crates/core/src/k8s_auth/api/types/auth.rs b/crates/api-types/src/k8s_auth/auth_conv.rs similarity index 60% rename from crates/core/src/k8s_auth/api/types/auth.rs rename to crates/api-types/src/k8s_auth/auth_conv.rs index 9a66640d..62423525 100644 --- a/crates/core/src/k8s_auth/api/types/auth.rs +++ b/crates/api-types/src/k8s_auth/auth_conv.rs @@ -13,18 +13,21 @@ // SPDX-License-Identifier: Apache-2.0 //! K8s auth provider types. -use openstack_keystone_api_types::k8s_auth::auth as api_auth; - use secrecy::{ExposeSecret, SecretString}; -use crate::k8s_auth::types; +use openstack_keystone_core_types::k8s_auth as provider_types; + +use crate::k8s_auth as api_types; -impl From<(api_auth::K8sAuthRequest, String)> for types::K8sAuthRequest { - fn from(value: (api_auth::K8sAuthRequest, String)) -> Self { - Self { - auth_instance_id: value.1, - jwt: SecretString::from(value.0.jwt.expose_secret()), - role_name: value.0.role_name, +impl api_types::K8sAuthRequest { + pub fn to_provider_with_instance_id( + self, + instance_id: String, + ) -> provider_types::K8sAuthRequest { + provider_types::K8sAuthRequest { + auth_instance_id: instance_id, + jwt: SecretString::from(self.jwt.expose_secret()), + role_name: self.role_name, } } } diff --git a/crates/api-types/src/k8s_auth/instance.rs b/crates/api-types/src/k8s_auth/instance.rs index 7b404f8c..8c030842 100644 --- a/crates/api-types/src/k8s_auth/instance.rs +++ b/crates/api-types/src/k8s_auth/instance.rs @@ -21,9 +21,9 @@ use crate::Link; /// K8s authentication instance. #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -#[cfg_attr(feature = "builder", derive(derive_builder::Builder))] #[cfg_attr( feature = "builder", + derive(derive_builder::Builder), builder( build_fn(error = "crate::error::BuilderError"), setter(strip_option, into) diff --git a/crates/core/src/k8s_auth/api/types/instance.rs b/crates/api-types/src/k8s_auth/instance_conv.rs similarity index 59% rename from crates/core/src/k8s_auth/api/types/instance.rs rename to crates/api-types/src/k8s_auth/instance_conv.rs index e2a9aabe..bf84b5df 100644 --- a/crates/core/src/k8s_auth/api/types/instance.rs +++ b/crates/api-types/src/k8s_auth/instance_conv.rs @@ -12,18 +12,12 @@ // // SPDX-License-Identifier: Apache-2.0 //! # Kubernetes auth instance types -use axum::{ - Json, - http::StatusCode, - response::{IntoResponse, Response}, -}; +use openstack_keystone_core_types::k8s_auth as provider_types; -use openstack_keystone_api_types::k8s_auth::instance as api_instance; +use crate::k8s_auth as api_types; -use crate::k8s_auth::types; - -impl From for api_instance::K8sAuthInstance { - fn from(value: types::K8sAuthInstance) -> Self { +impl From for api_types::K8sAuthInstance { + fn from(value: provider_types::K8sAuthInstance) -> Self { Self { ca_cert: value.ca_cert, disable_local_ca_jwt: value.disable_local_ca_jwt, @@ -36,8 +30,8 @@ impl From for api_instance::K8sAuthInstance { } } -impl From for types::K8sAuthInstanceCreate { - fn from(value: api_instance::K8sAuthInstanceCreateRequest) -> Self { +impl From for provider_types::K8sAuthInstanceCreate { + fn from(value: api_types::K8sAuthInstanceCreateRequest) -> Self { Self { ca_cert: value.instance.ca_cert, disable_local_ca_jwt: value.instance.disable_local_ca_jwt, @@ -50,8 +44,8 @@ impl From for types::K8sAuthInstance } } -impl From for types::K8sAuthInstanceUpdate { - fn from(value: api_instance::K8sAuthInstanceUpdateRequest) -> Self { +impl From for provider_types::K8sAuthInstanceUpdate { + fn from(value: api_types::K8sAuthInstanceUpdateRequest) -> Self { Self { ca_cert: value.instance.ca_cert, disable_local_ca_jwt: value.instance.disable_local_ca_jwt, @@ -62,20 +56,10 @@ impl From for types::K8sAuthInstance } } -impl IntoResponse for types::K8sAuthInstance { - fn into_response(self) -> Response { - ( - StatusCode::OK, - Json(api_instance::K8sAuthInstanceResponse { - instance: api_instance::K8sAuthInstance::from(self), - }), - ) - .into_response() - } -} - -impl From for types::K8sAuthInstanceListParameters { - fn from(value: api_instance::K8sAuthInstanceListParameters) -> Self { +impl From + for provider_types::K8sAuthInstanceListParameters +{ + fn from(value: api_types::K8sAuthInstanceListParameters) -> Self { Self { domain_id: value.domain_id, name: value.name, diff --git a/crates/core/src/k8s_auth/api/types/role.rs b/crates/api-types/src/k8s_auth/role_conv.rs similarity index 51% rename from crates/core/src/k8s_auth/api/types/role.rs rename to crates/api-types/src/k8s_auth/role_conv.rs index cad3677f..ca980fdf 100644 --- a/crates/core/src/k8s_auth/api/types/role.rs +++ b/crates/api-types/src/k8s_auth/role_conv.rs @@ -11,19 +11,12 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 -//! K8s auth role provider types. -use axum::{ - Json, - http::StatusCode, - response::{IntoResponse, Response}, -}; +use openstack_keystone_core_types::k8s_auth as provider_types; -use openstack_keystone_api_types::k8s_auth::role as api_role; +use crate::k8s_auth as api_types; -use crate::k8s_auth::types; - -impl From for api_role::K8sAuthRole { - fn from(value: types::K8sAuthRole) -> Self { +impl From for api_types::K8sAuthRole { + fn from(value: provider_types::K8sAuthRole) -> Self { Self { auth_instance_id: value.auth_instance_id, bound_audience: value.bound_audience, @@ -38,24 +31,24 @@ impl From for api_role::K8sAuthRole { } } -impl From<(api_role::K8sAuthRoleCreateRequest, String, String)> for types::K8sAuthRoleCreate { - fn from(value: (api_role::K8sAuthRoleCreateRequest, String, String)) -> Self { - Self { - auth_instance_id: value.1, - bound_audience: value.0.role.bound_audience, - bound_service_account_names: value.0.role.bound_service_account_names, - bound_service_account_namespaces: value.0.role.bound_service_account_namespaces, - domain_id: value.2, - enabled: value.0.role.enabled, - id: None, - name: value.0.role.name, - token_restriction_id: value.0.role.token_restriction_id, +impl From for provider_types::K8sAuthRoleCreateBuilder { + fn from(value: api_types::K8sAuthRoleCreateRequest) -> Self { + let role = value.role; + let mut builder = Self::default(); + builder.enabled(role.enabled); + builder.name(role.name); + builder.token_restriction_id(role.token_restriction_id); + builder.bound_service_account_namespaces(role.bound_service_account_namespaces); + builder.bound_service_account_names(role.bound_service_account_names); + if let Some(val) = &role.bound_audience { + builder.bound_audience(val); } + builder } } -impl From for types::K8sAuthRoleUpdate { - fn from(value: api_role::K8sAuthRoleUpdateRequest) -> Self { +impl From for provider_types::K8sAuthRoleUpdate { + fn from(value: api_types::K8sAuthRoleUpdateRequest) -> Self { Self { bound_audience: value.role.bound_audience, bound_service_account_names: value.role.bound_service_account_names, @@ -67,20 +60,8 @@ impl From for types::K8sAuthRoleUpdate { } } -impl IntoResponse for types::K8sAuthRole { - fn into_response(self) -> Response { - ( - StatusCode::OK, - Json(api_role::K8sAuthRoleResponse { - role: api_role::K8sAuthRole::from(self), - }), - ) - .into_response() - } -} - -impl From for types::K8sAuthRoleListParameters { - fn from(value: api_role::K8sAuthRoleListParameters) -> Self { +impl From for provider_types::K8sAuthRoleListParameters { + fn from(value: api_types::K8sAuthRoleListParameters) -> Self { Self { auth_instance_id: value.auth_instance_id, domain_id: value.domain_id, diff --git a/crates/api-types/src/lib.rs b/crates/api-types/src/lib.rs index d8378cbc..ef79b0e0 100644 --- a/crates/api-types/src/lib.rs +++ b/crates/api-types/src/lib.rs @@ -21,10 +21,16 @@ use serde::{Deserialize, Deserializer, Serialize}; use serde_json::Value; pub mod catalog; +#[cfg(feature = "conv")] +mod catalog_conv; pub mod error; +#[cfg(feature = "conv")] +mod error_conv; pub mod federation; pub mod k8s_auth; pub mod scope; +#[cfg(feature = "conv")] +mod scope_conv; pub mod trust; pub mod v3; pub mod v4; diff --git a/crates/api-types/src/scope_conv.rs b/crates/api-types/src/scope_conv.rs new file mode 100644 index 00000000..a289cff3 --- /dev/null +++ b/crates/api-types/src/scope_conv.rs @@ -0,0 +1,95 @@ +// 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 +//! Keystone API types. +use crate::scope as api_types; +// +//use openstack_keystone_core_types::scope as provider_types; + +impl From for api_types::Domain { + fn from(value: openstack_keystone_core_types::resource::Domain) -> Self { + Self { + id: Some(value.id), + name: Some(value.name), + } + } +} + +impl From<&openstack_keystone_core_types::resource::Domain> for api_types::Domain { + fn from(value: &openstack_keystone_core_types::resource::Domain) -> Self { + Self { + id: Some(value.id.clone()), + name: Some(value.name.clone()), + } + } +} + +impl From for openstack_keystone_core_types::scope::Domain { + fn from(value: api_types::Domain) -> Self { + Self { + id: value.id, + name: value.name, + } + } +} + +impl From for api_types::Domain { + fn from(value: openstack_keystone_core_types::scope::Domain) -> Self { + Self { + id: value.id, + name: value.name, + } + } +} + +impl From for openstack_keystone_core_types::scope::Project { + fn from(value: api_types::ScopeProject) -> Self { + Self { + id: value.id, + name: value.name, + domain: value.domain.map(Into::into), + } + } +} + +impl From for api_types::ScopeProject { + fn from(value: openstack_keystone_core_types::scope::Project) -> Self { + Self { + id: value.id, + name: value.name, + domain: value.domain.map(Into::into), + } + } +} + +impl From<&openstack_keystone_core_types::scope::Project> for api_types::ScopeProject { + fn from(value: &openstack_keystone_core_types::scope::Project) -> Self { + Self::from(value.clone()) + } +} + +impl From for openstack_keystone_core_types::scope::System { + fn from(value: api_types::System) -> Self { + Self { all: value.all } + } +} + +impl From for openstack_keystone_core_types::scope::Scope { + fn from(value: api_types::Scope) -> Self { + match value { + api_types::Scope::Project(scope) => Self::Project(scope.into()), + api_types::Scope::Domain(scope) => Self::Domain(scope.into()), + api_types::Scope::System(scope) => Self::System(scope.into()), + } + } +} diff --git a/crates/api-types/src/trust.rs b/crates/api-types/src/trust.rs index 5bba2451..50de14cc 100644 --- a/crates/api-types/src/trust.rs +++ b/crates/api-types/src/trust.rs @@ -16,3 +16,22 @@ pub mod trust; pub use trust::*; + +#[cfg(feature = "conv")] +mod trust_conv; + +#[cfg(feature = "conv")] +use openstack_keystone_core_types::trust::TrustProviderError; +#[cfg(feature = "conv")] +impl From for crate::error::KeystoneApiError { + fn from(source: TrustProviderError) -> Self { + match source { + TrustProviderError::Conflict(x) => Self::Conflict(x), + TrustProviderError::ExpirationImpossible => Self::forbidden(source), + TrustProviderError::RedelegatedRolesNotAvailable => Self::forbidden(source), + TrustProviderError::RedelegationDeepnessExceed { .. } => Self::forbidden(source), + TrustProviderError::RemainingUsesExceed => Self::forbidden(source), + other => Self::InternalError(other.to_string()), + } + } +} diff --git a/crates/core/src/trust/api/types/trust.rs b/crates/api-types/src/trust/trust_conv.rs similarity index 76% rename from crates/core/src/trust/api/types/trust.rs rename to crates/api-types/src/trust/trust_conv.rs index 3f6f3af2..f91a88be 100644 --- a/crates/core/src/trust/api/types/trust.rs +++ b/crates/api-types/src/trust/trust_conv.rs @@ -11,12 +11,13 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 -use crate::trust::types::Trust; -pub use openstack_keystone_api_types::trust as api_trust; +pub use openstack_keystone_core_types::trust as provider_types; -impl From<&Trust> for api_trust::TokenTrustRepr { - fn from(value: &Trust) -> Self { +use crate::trust as api_types; + +impl From<&provider_types::Trust> for api_types::TokenTrustRepr { + fn from(value: &provider_types::Trust) -> Self { Self { expires_at: value.expires_at, id: value.id.clone(), @@ -24,10 +25,10 @@ impl From<&Trust> for api_trust::TokenTrustRepr { remaining_uses: value.remaining_uses, redelegated_trust_id: value.redelegated_trust_id.clone(), redelegation_count: value.redelegation_count, - trustor_user: api_trust::TokenTrustUser { + trustor_user: api_types::TokenTrustUser { id: value.trustor_user_id.clone(), }, - trustee_user: api_trust::TokenTrustUser { + trustee_user: api_types::TokenTrustUser { id: value.trustee_user_id.clone(), }, } diff --git a/crates/api-types/src/v3.rs b/crates/api-types/src/v3.rs index 42c4c5df..97dd5bc1 100644 --- a/crates/api-types/src/v3.rs +++ b/crates/api-types/src/v3.rs @@ -18,3 +18,16 @@ pub mod project; pub mod role; pub mod role_assignment; pub mod user; + +#[cfg(feature = "conv")] +mod auth_conv; +#[cfg(feature = "conv")] +mod group_conv; +#[cfg(feature = "conv")] +mod project_conv; +#[cfg(feature = "conv")] +mod role_assignment_conv; +#[cfg(feature = "conv")] +mod role_conv; +#[cfg(feature = "conv")] +mod user_conv; diff --git a/crates/api-types/src/v3/auth_conv.rs b/crates/api-types/src/v3/auth_conv.rs new file mode 100644 index 00000000..d1991dda --- /dev/null +++ b/crates/api-types/src/v3/auth_conv.rs @@ -0,0 +1,64 @@ +// 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 + +use openstack_keystone_core_types::error::BuilderError; + +use crate::v3::auth::token as api_types; + +impl TryFrom + for openstack_keystone_core_types::identity::UserPasswordAuthRequest +{ + type Error = BuilderError; + + fn try_from(value: api_types::UserPassword) -> Result { + let mut upa = + openstack_keystone_core_types::identity::UserPasswordAuthRequestBuilder::default(); + if let Some(id) = &value.id { + upa.id(id); + } + if let Some(name) = &value.name { + upa.name(name); + } + if let Some(domain) = &value.domain { + let mut domain_builder = + openstack_keystone_core_types::identity::DomainBuilder::default(); + if let Some(id) = &domain.id { + domain_builder.id(id); + } + if let Some(name) = &domain.name { + domain_builder.name(name); + } + upa.domain(domain_builder.build()?); + } + upa.password(value.password.clone()); + upa.build() + } +} + +impl TryFrom<&openstack_keystone_core_types::token::Token> for api_types::Token { + type Error = BuilderError; + + fn try_from(value: &openstack_keystone_core_types::token::Token) -> Result { + let mut token = api_types::TokenBuilder::default(); + token.user( + api_types::UserBuilder::default() + .id(value.user_id()) + .build()?, + ); + token.methods(value.methods().clone()); + token.audit_ids(value.audit_ids().clone()); + token.expires_at(*value.expires_at()); + token.build() + } +} diff --git a/crates/core/src/api/v3/group.rs b/crates/api-types/src/v3/group_conv.rs similarity index 61% rename from crates/core/src/api/v3/group.rs rename to crates/api-types/src/v3/group_conv.rs index cfc059da..eeaaa94a 100644 --- a/crates/core/src/api/v3/group.rs +++ b/crates/api-types/src/v3/group_conv.rs @@ -12,18 +12,12 @@ // // SPDX-License-Identifier: Apache-2.0 -use axum::{ - Json, - http::StatusCode, - response::{IntoResponse, Response}, -}; +use openstack_keystone_core_types::identity as provider_types; -pub use openstack_keystone_api_types::v3::group::*; +use crate::v3::group as api_types; -use crate::identity::types; - -impl From for Group { - fn from(value: types::Group) -> Self { +impl From for api_types::Group { + fn from(value: provider_types::Group) -> Self { Self { id: value.id, domain_id: value.domain_id, @@ -34,8 +28,8 @@ impl From for Group { } } -impl From for types::GroupCreate { - fn from(value: GroupCreateRequest) -> Self { +impl From for provider_types::GroupCreate { + fn from(value: api_types::GroupCreateRequest) -> Self { let group = value.group; Self { id: None, @@ -47,20 +41,8 @@ impl From for types::GroupCreate { } } -impl IntoResponse for types::Group { - fn into_response(self) -> Response { - ( - StatusCode::OK, - Json(GroupResponse { - group: Group::from(self), - }), - ) - .into_response() - } -} - -impl From for types::GroupListParameters { - fn from(value: GroupListParameters) -> Self { +impl From for provider_types::GroupListParameters { + fn from(value: api_types::GroupListParameters) -> Self { Self { domain_id: value.domain_id, name: value.name, diff --git a/crates/core/src/api/v3/project.rs b/crates/api-types/src/v3/project_conv.rs similarity index 80% rename from crates/core/src/api/v3/project.rs rename to crates/api-types/src/v3/project_conv.rs index 7072587f..6c472fd3 100644 --- a/crates/core/src/api/v3/project.rs +++ b/crates/api-types/src/v3/project_conv.rs @@ -13,11 +13,11 @@ // SPDX-License-Identifier: Apache-2.0 //! Project API types. -pub use openstack_keystone_api_types::v3::project::*; +use openstack_keystone_core_types::resource as provider_types; -use crate::resource::types as provider_types; +use crate::v3::project as api_types; -impl From for ProjectShort { +impl From for api_types::ProjectShort { fn from(value: provider_types::Project) -> Self { Self { domain_id: value.domain_id, @@ -28,7 +28,7 @@ impl From for ProjectShort { } } -impl From<&provider_types::Project> for ProjectShort { +impl From<&provider_types::Project> for api_types::ProjectShort { fn from(value: &provider_types::Project) -> Self { Self { domain_id: value.domain_id.clone(), @@ -39,7 +39,7 @@ impl From<&provider_types::Project> for ProjectShort { } } -impl From for Project { +impl From for api_types::Project { fn from(value: provider_types::Project) -> Self { Self { description: value.description, @@ -54,8 +54,8 @@ impl From for Project { } } -impl From for provider_types::ProjectCreate { - fn from(value: ProjectCreate) -> Self { +impl From for provider_types::ProjectCreate { + fn from(value: api_types::ProjectCreate) -> Self { Self { description: value.description, domain_id: value.domain_id, diff --git a/crates/core/src/api/v3/role_assignment.rs b/crates/api-types/src/v3/role_assignment_conv.rs similarity index 64% rename from crates/core/src/api/v3/role_assignment.rs rename to crates/api-types/src/v3/role_assignment_conv.rs index 05677997..e1cea679 100644 --- a/crates/core/src/api/v3/role_assignment.rs +++ b/crates/api-types/src/v3/role_assignment_conv.rs @@ -12,54 +12,54 @@ // // SPDX-License-Identifier: Apache-2.0 -pub use openstack_keystone_api_types::v3::role_assignment::*; +use openstack_keystone_core_types::assignment as provider_types; -use crate::api::error::KeystoneApiError; -use crate::assignment::types; +use crate::error::KeystoneApiError; +use crate::v3::role_assignment as api_types; -impl TryFrom for Assignment { +impl TryFrom for api_types::Assignment { type Error = KeystoneApiError; - fn try_from(value: types::Assignment) -> Result { - let mut builder = AssignmentBuilder::default(); - builder.role(Role { + fn try_from(value: provider_types::Assignment) -> Result { + let mut builder = api_types::AssignmentBuilder::default(); + builder.role(api_types::Role { id: value.role_id, name: value.role_name, }); match value.r#type { - types::AssignmentType::GroupDomain => { - builder.group(Group { id: value.actor_id }); - builder.scope(Scope::Domain(Domain { + provider_types::AssignmentType::GroupDomain => { + builder.group(api_types::Group { id: value.actor_id }); + builder.scope(api_types::Scope::Domain(api_types::Domain { id: value.target_id, })); } - types::AssignmentType::GroupProject => { - builder.group(Group { id: value.actor_id }); - builder.scope(Scope::Project(Project { + provider_types::AssignmentType::GroupProject => { + builder.group(api_types::Group { id: value.actor_id }); + builder.scope(api_types::Scope::Project(api_types::Project { id: value.target_id, })); } - types::AssignmentType::UserDomain => { - builder.user(User { id: value.actor_id }); - builder.scope(Scope::Domain(Domain { + provider_types::AssignmentType::UserDomain => { + builder.user(api_types::User { id: value.actor_id }); + builder.scope(api_types::Scope::Domain(api_types::Domain { id: value.target_id, })); } - types::AssignmentType::UserProject => { - builder.user(User { id: value.actor_id }); - builder.scope(Scope::Project(Project { + provider_types::AssignmentType::UserProject => { + builder.user(api_types::User { id: value.actor_id }); + builder.scope(api_types::Scope::Project(api_types::Project { id: value.target_id, })); } - types::AssignmentType::UserSystem => { - builder.user(User { id: value.actor_id }); - builder.scope(Scope::System(System { + provider_types::AssignmentType::UserSystem => { + builder.user(api_types::User { id: value.actor_id }); + builder.scope(api_types::Scope::System(api_types::System { id: value.target_id, })); } - types::AssignmentType::GroupSystem => { - builder.group(Group { id: value.actor_id }); - builder.scope(Scope::System(System { + provider_types::AssignmentType::GroupSystem => { + builder.group(api_types::Group { id: value.actor_id }); + builder.scope(api_types::Scope::System(api_types::System { id: value.target_id, })); } @@ -68,11 +68,13 @@ impl TryFrom for Assignment { } } -impl TryFrom for types::RoleAssignmentListParameters { +impl TryFrom + for provider_types::RoleAssignmentListParameters +{ type Error = KeystoneApiError; - fn try_from(value: RoleAssignmentListParameters) -> Result { - let mut builder = types::RoleAssignmentListParametersBuilder::default(); + fn try_from(value: api_types::RoleAssignmentListParameters) -> Result { + let mut builder = provider_types::RoleAssignmentListParametersBuilder::default(); // Filter by role if let Some(val) = &value.role_id { builder.role_id(val); @@ -104,8 +106,8 @@ impl TryFrom for types::RoleAssignmentListParamete #[cfg(test)] mod tests { - use super::*; - use crate::assignment::types; + use crate::v3::role_assignment::*; + use openstack_keystone_core_types::assignment as provider_types; #[test] fn test_assignment_conversion() { @@ -121,12 +123,12 @@ mod tests { }), group: None, }, - Assignment::try_from(types::Assignment { + Assignment::try_from(provider_types::Assignment { role_id: "role".into(), role_name: Some("role_name".into()), actor_id: "actor".into(), target_id: "target".into(), - r#type: types::AssignmentType::UserProject, + r#type: provider_types::AssignmentType::UserProject, inherited: false, implied_via: None, }) @@ -144,12 +146,12 @@ mod tests { }), group: None, }, - Assignment::try_from(types::Assignment { + Assignment::try_from(provider_types::Assignment { role_id: "role".into(), role_name: None, actor_id: "actor".into(), target_id: "target".into(), - r#type: types::AssignmentType::UserDomain, + r#type: provider_types::AssignmentType::UserDomain, inherited: false, implied_via: None, }) @@ -167,12 +169,12 @@ mod tests { }), user: None, }, - Assignment::try_from(types::Assignment { + Assignment::try_from(provider_types::Assignment { role_id: "role".into(), role_name: None, actor_id: "actor".into(), target_id: "target".into(), - r#type: types::AssignmentType::GroupProject, + r#type: provider_types::AssignmentType::GroupProject, inherited: false, implied_via: None, }) @@ -190,12 +192,12 @@ mod tests { }), user: None, }, - Assignment::try_from(types::Assignment { + Assignment::try_from(provider_types::Assignment { role_id: "role".into(), role_name: None, actor_id: "actor".into(), target_id: "target".into(), - r#type: types::AssignmentType::GroupDomain, + r#type: provider_types::AssignmentType::GroupDomain, inherited: false, implied_via: None, }) diff --git a/crates/core/src/api/v3/role.rs b/crates/api-types/src/v3/role_conv.rs similarity index 62% rename from crates/core/src/api/v3/role.rs rename to crates/api-types/src/v3/role_conv.rs index 9eefd2ba..28136443 100644 --- a/crates/core/src/api/v3/role.rs +++ b/crates/api-types/src/v3/role_conv.rs @@ -12,18 +12,12 @@ // // SPDX-License-Identifier: Apache-2.0 -use axum::{ - Json, - http::StatusCode, - response::{IntoResponse, Response}, -}; +use openstack_keystone_core_types::role as provider_types; -pub use openstack_keystone_api_types::v3::role::*; +use crate::v3::role as api_types; -use crate::role::types; - -impl From for Role { - fn from(value: types::Role) -> Self { +impl From for api_types::Role { + fn from(value: provider_types::Role) -> Self { Self { id: value.id, domain_id: value.domain_id, @@ -34,8 +28,8 @@ impl From for Role { } } -impl From for RoleRef { - fn from(value: types::RoleRef) -> Self { +impl From for api_types::RoleRef { + fn from(value: provider_types::RoleRef) -> Self { Self { id: value.id, domain_id: value.domain_id, @@ -44,20 +38,8 @@ impl From for RoleRef { } } -impl IntoResponse for types::Role { - fn into_response(self) -> Response { - ( - StatusCode::OK, - Json(RoleResponse { - role: Role::from(self), - }), - ) - .into_response() - } -} - -impl From for types::RoleListParameters { - fn from(value: RoleListParameters) -> Self { +impl From for provider_types::RoleListParameters { + fn from(value: api_types::RoleListParameters) -> Self { Self { domain_id: Some(value.domain_id), name: value.name, @@ -65,8 +47,8 @@ impl From for types::RoleListParameters { } } -impl From for types::RoleCreate { - fn from(value: RoleCreate) -> Self { +impl From for provider_types::RoleCreate { + fn from(value: api_types::RoleCreate) -> Self { Self { description: value.description, domain_id: value.domain_id, diff --git a/crates/core/src/api/v3/user.rs b/crates/api-types/src/v3/user_conv.rs similarity index 73% rename from crates/core/src/api/v3/user.rs rename to crates/api-types/src/v3/user_conv.rs index 44b6919b..2f74b585 100644 --- a/crates/core/src/api/v3/user.rs +++ b/crates/api-types/src/v3/user_conv.rs @@ -12,18 +12,12 @@ // // SPDX-License-Identifier: Apache-2.0 -use axum::{ - Json, - http::StatusCode, - response::{IntoResponse, Response}, -}; +use openstack_keystone_core_types::identity as provider_types; -pub use openstack_keystone_api_types::v3::user::*; +use crate::v3::user as api_types; -use crate::identity::types as identity_types; - -impl From for UserOptions { - fn from(value: identity_types::UserOptions) -> Self { +impl From for api_types::UserOptions { + fn from(value: provider_types::UserOptions) -> Self { Self { ignore_change_password_upon_first_use: value.ignore_change_password_upon_first_use, ignore_password_expiry: value.ignore_password_expiry, @@ -36,8 +30,8 @@ impl From for UserOptions { } } -impl From for identity_types::UserOptions { - fn from(value: UserOptions) -> Self { +impl From for provider_types::UserOptions { + fn from(value: api_types::UserOptions) -> Self { Self { ignore_change_password_upon_first_use: value.ignore_change_password_upon_first_use, ignore_password_expiry: value.ignore_password_expiry, @@ -51,9 +45,9 @@ impl From for identity_types::UserOptions { } } -impl From for User { - fn from(value: identity_types::UserResponse) -> Self { - let opts: UserOptions = value.options.clone().into(); +impl From for api_types::User { + fn from(value: provider_types::UserResponse) -> Self { + let opts: api_types::UserOptions = value.options.clone().into(); // We only want to see user options if there is at least 1 option set let opts = if opts.ignore_change_password_upon_first_use.is_some() || opts.ignore_password_expiry.is_some() @@ -83,8 +77,8 @@ impl From for User { } } -impl From for identity_types::UserCreate { - fn from(value: UserCreateRequest) -> Self { +impl From for provider_types::UserCreate { + fn from(value: api_types::UserCreateRequest) -> Self { let user = value.user; Self { default_project_id: user.default_project_id, @@ -100,16 +94,16 @@ impl From for identity_types::UserCreate { } } -impl From for Federation { - fn from(value: identity_types::Federation) -> Self { +impl From for api_types::Federation { + fn from(value: provider_types::Federation) -> Self { Self { idp_id: value.idp_id, protocols: value.protocols.into_iter().map(Into::into).collect(), } } } -impl From for FederationProtocol { - fn from(value: identity_types::FederationProtocol) -> Self { +impl From for api_types::FederationProtocol { + fn from(value: provider_types::FederationProtocol) -> Self { Self { protocol_id: value.protocol_id, unique_id: value.unique_id, @@ -117,20 +111,8 @@ impl From for FederationProtocol { } } -impl IntoResponse for identity_types::UserResponse { - fn into_response(self) -> Response { - ( - StatusCode::OK, - Json(UserResponse { - user: User::from(self), - }), - ) - .into_response() - } -} - -impl From for identity_types::UserListParameters { - fn from(value: UserListParameters) -> Self { +impl From for provider_types::UserListParameters { + fn from(value: api_types::UserListParameters) -> Self { Self { domain_id: value.domain_id, name: value.name, diff --git a/crates/api-types/src/v4.rs b/crates/api-types/src/v4.rs index ade489a8..1ec8f559 100644 --- a/crates/api-types/src/v4.rs +++ b/crates/api-types/src/v4.rs @@ -15,3 +15,6 @@ pub mod auth; pub mod token_restriction; pub mod user; + +#[cfg(feature = "conv")] +mod token_restriction_conv; diff --git a/crates/core/src/api/v4/token_restriction.rs b/crates/api-types/src/v4/token_restriction_conv.rs similarity index 63% rename from crates/core/src/api/v4/token_restriction.rs rename to crates/api-types/src/v4/token_restriction_conv.rs index 8fc8a056..2139fa9c 100644 --- a/crates/core/src/api/v4/token_restriction.rs +++ b/crates/api-types/src/v4/token_restriction_conv.rs @@ -12,22 +12,15 @@ // // SPDX-License-Identifier: Apache-2.0 //! Token restriction types. -use axum::{ - Json, - http::StatusCode, - response::{IntoResponse, Response}, -}; -pub use openstack_keystone_api_types::v4::token_restriction::*; +use openstack_keystone_core_types::token as provider_types; -use crate::token::types::{ - self as types, TokenRestriction as ProviderTokenRestriction, - TokenRestrictionCreate as ProviderTokenRestrictionCreate, - TokenRestrictionUpdate as ProviderTokenRestrictionUpdate, -}; +use crate::v4::token_restriction as api_types; -impl From for types::TokenRestrictionListParameters { - fn from(value: TokenRestrictionListParameters) -> Self { +impl From + for provider_types::TokenRestrictionListParameters +{ + fn from(value: api_types::TokenRestrictionListParameters) -> Self { Self { domain_id: value.domain_id, user_id: value.user_id, @@ -36,8 +29,8 @@ impl From for types::TokenRestrictionListParamet } } -impl From for TokenRestriction { - fn from(value: ProviderTokenRestriction) -> Self { +impl From for api_types::TokenRestriction { + fn from(value: provider_types::TokenRestriction) -> Self { Self { allow_rescope: value.allow_rescope, allow_renew: value.allow_renew, @@ -53,8 +46,8 @@ impl From for TokenRestriction { } } -impl From for ProviderTokenRestrictionCreate { - fn from(value: TokenRestrictionCreateRequest) -> Self { +impl From for provider_types::TokenRestrictionCreate { + fn from(value: api_types::TokenRestrictionCreateRequest) -> Self { Self { allow_rescope: value.restriction.allow_rescope, allow_renew: value.restriction.allow_renew, @@ -72,8 +65,8 @@ impl From for ProviderTokenRestrictionCreate { } } -impl From for ProviderTokenRestrictionUpdate { - fn from(value: TokenRestrictionUpdateRequest) -> Self { +impl From for provider_types::TokenRestrictionUpdate { + fn from(value: api_types::TokenRestrictionUpdateRequest) -> Self { Self { allow_rescope: value.restriction.allow_rescope, allow_renew: value.restriction.allow_renew, @@ -86,15 +79,3 @@ impl From for ProviderTokenRestrictionUpdate { } } } - -impl IntoResponse for ProviderTokenRestriction { - fn into_response(self) -> Response { - ( - StatusCode::OK, - Json(TokenRestrictionResponse { - restriction: TokenRestriction::from(self), - }), - ) - .into_response() - } -} diff --git a/crates/appcred-sql/Cargo.toml b/crates/appcred-sql/Cargo.toml index 8e75fb20..5a2be938 100644 --- a/crates/appcred-sql/Cargo.toml +++ b/crates/appcred-sql/Cargo.toml @@ -15,6 +15,7 @@ async-trait.workspace = true chrono.workspace = true openstack-keystone-config = { version = "0.1", path = "../config" } openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } secrecy.workspace = true sea-orm.workspace = true tokio = { workspace = true, features = ["macros"] } diff --git a/crates/appcred-sql/src/application_credential.rs b/crates/appcred-sql/src/application_credential.rs index 3faa0142..99782768 100644 --- a/crates/appcred-sql/src/application_credential.rs +++ b/crates/appcred-sql/src/application_credential.rs @@ -16,8 +16,8 @@ use chrono::DateTime; use openstack_keystone_core::application_credential::ApplicationCredentialProviderError; -use openstack_keystone_core::application_credential::types::*; -use openstack_keystone_core::role::types::RoleRef; +use openstack_keystone_core_types::application_credential::*; +use openstack_keystone_core_types::role::RoleRef; use crate::entity::{ access_rule as db_access_rule, application_credential as db_application_credential, diff --git a/crates/appcred-sql/src/application_credential/create.rs b/crates/appcred-sql/src/application_credential/create.rs index 1d70e055..e22ae7dd 100644 --- a/crates/appcred-sql/src/application_credential/create.rs +++ b/crates/appcred-sql/src/application_credential/create.rs @@ -20,9 +20,9 @@ use uuid::Uuid; use openstack_keystone_config::Config; use openstack_keystone_core::application_credential::ApplicationCredentialProviderError; -use openstack_keystone_core::application_credential::types::*; use openstack_keystone_core::common::password_hashing; use openstack_keystone_core::error::DbContextExt; +use openstack_keystone_core_types::application_credential::*; use crate::entity::{ access_rule as db_access_rule, application_credential as db_application_credential, @@ -67,7 +67,11 @@ pub async fn create( .context("starting transaction for persisting application credential")?; let mut model = db_application_credential::ActiveModel::try_from(rec.clone())?; model.secret_hash = if let Some(secret) = &rec.secret { - Set(password_hashing::hash_password(conf, secret.expose_secret()).await?) + Set( + password_hashing::hash_password(conf, secret.expose_secret()) + .await + .map_err(ApplicationCredentialProviderError::password_hash)?, + ) } else { return Err(ApplicationCredentialProviderError::SecretMissing); }; @@ -194,8 +198,9 @@ mod tests { use chrono::{Timelike, Utc}; use sea_orm::{DatabaseBackend, MockDatabase, MockExecResult, Statement, Transaction}; + use openstack_keystone_core_types::role::RoleRef; + use openstack_keystone_config::PasswordHashingAlgo; - use openstack_keystone_core::role::types::RoleRef; use super::super::tests::*; use super::*; diff --git a/crates/appcred-sql/src/application_credential/get.rs b/crates/appcred-sql/src/application_credential/get.rs index f526b3b7..5091dec5 100644 --- a/crates/appcred-sql/src/application_credential/get.rs +++ b/crates/appcred-sql/src/application_credential/get.rs @@ -17,9 +17,9 @@ use sea_orm::entity::*; use sea_orm::query::*; use openstack_keystone_core::application_credential::ApplicationCredentialProviderError; -use openstack_keystone_core::application_credential::types::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::role::types::RoleRef; +use openstack_keystone_core_types::application_credential::*; +use openstack_keystone_core_types::role::RoleRef; use crate::entity::{ application_credential as db_application_credential, diff --git a/crates/appcred-sql/src/application_credential/list.rs b/crates/appcred-sql/src/application_credential/list.rs index 1d4fc920..0c026e09 100644 --- a/crates/appcred-sql/src/application_credential/list.rs +++ b/crates/appcred-sql/src/application_credential/list.rs @@ -18,8 +18,8 @@ use sea_orm::query::*; use sea_orm::{Cursor, SelectModel}; use openstack_keystone_core::application_credential::ApplicationCredentialProviderError; -use openstack_keystone_core::application_credential::types::*; use openstack_keystone_core::error::DbContextExt; +use openstack_keystone_core_types::application_credential::*; use crate::entity::{ application_credential as db_application_credential, diff --git a/crates/appcred-sql/src/lib.rs b/crates/appcred-sql/src/lib.rs index 2d777a30..1055c3b8 100644 --- a/crates/appcred-sql/src/lib.rs +++ b/crates/appcred-sql/src/lib.rs @@ -15,11 +15,11 @@ use async_trait::async_trait; -use openstack_keystone_core::application_credential::types::*; use openstack_keystone_core::application_credential::{ ApplicationCredentialProviderError, backend::ApplicationCredentialBackend, }; use openstack_keystone_core::keystone::ServiceState; +use openstack_keystone_core_types::application_credential::*; mod application_credential; pub mod entity; diff --git a/crates/assignment-sql/Cargo.toml b/crates/assignment-sql/Cargo.toml index a1b6f923..17a374ac 100644 --- a/crates/assignment-sql/Cargo.toml +++ b/crates/assignment-sql/Cargo.toml @@ -14,6 +14,7 @@ exclude.workspace = true async-trait.workspace = true openstack-keystone-config = { version = "0.1", path = "../config" } openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } sea-orm.workspace = true tokio = { workspace = true, features = ["macros"] } tracing.workspace = true diff --git a/crates/assignment-sql/src/assignment.rs b/crates/assignment-sql/src/assignment.rs index 7857bd3f..ba62445f 100644 --- a/crates/assignment-sql/src/assignment.rs +++ b/crates/assignment-sql/src/assignment.rs @@ -13,7 +13,8 @@ // SPDX-License-Identifier: Apache-2.0 //! Role assignment database backend. -use openstack_keystone_core::assignment::{AssignmentProviderError, types::*}; +use openstack_keystone_core::assignment::AssignmentProviderError; +use openstack_keystone_core_types::assignment::*; use crate::entity::{ assignment as db_assignment, sea_orm_active_enums::Type as DbAssignmentType, @@ -53,7 +54,19 @@ impl TryFrom for Assignment { builder.actor_id(value.actor_id); builder.target_id(value.target_id); builder.inherited(value.inherited); - builder.r#type(AssignmentType::try_from(value.r#type.as_ref())?); + builder.r#type(match value.r#type.as_ref() { + "GroupDomain" => AssignmentType::GroupDomain, + "GroupProject" => AssignmentType::GroupProject, + "GroupSystem" => AssignmentType::GroupSystem, + "UserDomain" => AssignmentType::UserDomain, + "UserProject" => AssignmentType::UserProject, + "UserSystem" => AssignmentType::UserSystem, + _ => { + return Err(AssignmentProviderError::InvalidAssignmentType( + value.r#type.clone(), + )); + } + }); Ok(builder.build()?) } diff --git a/crates/assignment-sql/src/assignment/check.rs b/crates/assignment-sql/src/assignment/check.rs index 751f9be6..3b2dbf36 100644 --- a/crates/assignment-sql/src/assignment/check.rs +++ b/crates/assignment-sql/src/assignment/check.rs @@ -17,11 +17,9 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use sea_orm::query::*; -use openstack_keystone_core::assignment::{ - AssignmentProviderError, - types::{Assignment, AssignmentType}, -}; +use openstack_keystone_core::assignment::AssignmentProviderError; use openstack_keystone_core::error::DbContextExt; +use openstack_keystone_core_types::assignment::*; use crate::entity::{ assignment as db_assignment, diff --git a/crates/assignment-sql/src/assignment/create.rs b/crates/assignment-sql/src/assignment/create.rs index 83858177..f2b3007a 100644 --- a/crates/assignment-sql/src/assignment/create.rs +++ b/crates/assignment-sql/src/assignment/create.rs @@ -15,11 +15,9 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; -use openstack_keystone_core::assignment::{ - AssignmentProviderError, - types::{Assignment, AssignmentCreate, AssignmentType}, -}; +use openstack_keystone_core::assignment::AssignmentProviderError; use openstack_keystone_core::error::DbContextExt; +use openstack_keystone_core_types::assignment::*; use crate::entity::{ assignment as db_assignment, sea_orm_active_enums::Type as DbAssignmentType, diff --git a/crates/assignment-sql/src/assignment/delete.rs b/crates/assignment-sql/src/assignment/delete.rs index 9f73189d..ff527781 100644 --- a/crates/assignment-sql/src/assignment/delete.rs +++ b/crates/assignment-sql/src/assignment/delete.rs @@ -13,11 +13,9 @@ // SPDX-License-Identifier: Apache-2.0 use sea_orm::{DatabaseConnection, EntityTrait}; -use openstack_keystone_core::assignment::{ - AssignmentProviderError, - types::{Assignment, AssignmentType}, -}; +use openstack_keystone_core::assignment::AssignmentProviderError; use openstack_keystone_core::error::DbContextExt; +use openstack_keystone_core_types::assignment::*; use crate::entity::{ assignment as db_assignment, sea_orm_active_enums::Type as DbAssignmentType, diff --git a/crates/assignment-sql/src/assignment/list.rs b/crates/assignment-sql/src/assignment/list.rs index 44daa1de..f41d48e5 100644 --- a/crates/assignment-sql/src/assignment/list.rs +++ b/crates/assignment-sql/src/assignment/list.rs @@ -16,13 +16,9 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use sea_orm::query::*; -use openstack_keystone_core::assignment::{ - AssignmentProviderError, - types::{ - Assignment, RoleAssignmentListForMultipleActorTargetParameters, RoleAssignmentTargetType, - }, -}; +use openstack_keystone_core::assignment::AssignmentProviderError; use openstack_keystone_core::error::DbContextExt; +use openstack_keystone_core_types::assignment::*; use crate::entity::{ assignment as db_assignment, @@ -176,7 +172,7 @@ async fn list_for_multiple_actors_and_targets_system( mod tests { use sea_orm::{DatabaseBackend, MockDatabase, Transaction}; - use openstack_keystone_core::assignment::types::{AssignmentType, RoleAssignmentTarget}; + use openstack_keystone_core_types::assignment::*; use super::super::tests::*; use super::*; diff --git a/crates/assignment-sql/src/lib.rs b/crates/assignment-sql/src/lib.rs index b843ad16..ed803c7e 100644 --- a/crates/assignment-sql/src/lib.rs +++ b/crates/assignment-sql/src/lib.rs @@ -16,15 +16,13 @@ use async_trait::async_trait; use std::collections::{BTreeMap, HashSet}; -use openstack_keystone_core::assignment::types::*; use openstack_keystone_core::assignment::{AssignmentProviderError, backend::AssignmentBackend}; use openstack_keystone_core::identity::IdentityApi; use openstack_keystone_core::keystone::ServiceState; use openstack_keystone_core::resource::ResourceApi; -use openstack_keystone_core::role::{ - RoleApi, - types::{Role, RoleListParameters}, -}; +use openstack_keystone_core::role::RoleApi; +use openstack_keystone_core_types::assignment::*; +use openstack_keystone_core_types::role::*; mod assignment; pub mod entity; @@ -195,7 +193,8 @@ mod tests { use openstack_keystone_core::keystone::Service; use openstack_keystone_core::policy::MockPolicy; use openstack_keystone_core::provider::Provider; - use openstack_keystone_core::role::{MockRoleProvider, types::RoleBuilder}; + use openstack_keystone_core::role::MockRoleProvider; + use openstack_keystone_core_types::role::RoleBuilder; use super::assignment::tests::*; use super::*; diff --git a/crates/catalog-sql/Cargo.toml b/crates/catalog-sql/Cargo.toml index a8676e9e..761f94ce 100644 --- a/crates/catalog-sql/Cargo.toml +++ b/crates/catalog-sql/Cargo.toml @@ -13,6 +13,7 @@ exclude.workspace = true [dependencies] async-trait.workspace = true openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } sea-orm.workspace = true serde_json.workspace = true tracing.workspace = true diff --git a/crates/catalog-sql/src/endpoint.rs b/crates/catalog-sql/src/endpoint.rs index 9ace55aa..3242dd9b 100644 --- a/crates/catalog-sql/src/endpoint.rs +++ b/crates/catalog-sql/src/endpoint.rs @@ -15,10 +15,8 @@ use serde_json::Value; use tracing::error; -use openstack_keystone_core::catalog::{ - CatalogProviderError, - types::{Endpoint, EndpointBuilder}, -}; +use openstack_keystone_core::catalog::CatalogProviderError; +use openstack_keystone_core_types::catalog::*; use crate::entity::endpoint as db_endpoint; diff --git a/crates/catalog-sql/src/endpoint/get.rs b/crates/catalog-sql/src/endpoint/get.rs index 447a9d49..f0d1d617 100644 --- a/crates/catalog-sql/src/endpoint/get.rs +++ b/crates/catalog-sql/src/endpoint/get.rs @@ -15,8 +15,9 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; -use openstack_keystone_core::catalog::{CatalogProviderError, types::Endpoint}; +use openstack_keystone_core::catalog::CatalogProviderError; use openstack_keystone_core::error::DbContextExt; +use openstack_keystone_core_types::catalog::*; use crate::entity::prelude::Endpoint as DbEndpoint; diff --git a/crates/catalog-sql/src/endpoint/list.rs b/crates/catalog-sql/src/endpoint/list.rs index 643389ac..1a29aaec 100644 --- a/crates/catalog-sql/src/endpoint/list.rs +++ b/crates/catalog-sql/src/endpoint/list.rs @@ -16,11 +16,9 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use sea_orm::query::*; -use openstack_keystone_core::catalog::{ - CatalogProviderError, - types::{Endpoint, EndpointListParameters}, -}; +use openstack_keystone_core::catalog::CatalogProviderError; use openstack_keystone_core::error::DbContextExt; +use openstack_keystone_core_types::catalog::*; use crate::entity::{endpoint as db_endpoint, prelude::Endpoint as DbEndpoint}; diff --git a/crates/catalog-sql/src/lib.rs b/crates/catalog-sql/src/lib.rs index ae29e7cf..684f321e 100644 --- a/crates/catalog-sql/src/lib.rs +++ b/crates/catalog-sql/src/lib.rs @@ -20,9 +20,9 @@ use sea_orm::query::*; use openstack_keystone_core::catalog::CatalogProviderError; use openstack_keystone_core::catalog::backend::CatalogBackend; -use openstack_keystone_core::catalog::types::*; use openstack_keystone_core::error::DbContextExt; use openstack_keystone_core::keystone::ServiceState; +use openstack_keystone_core_types::catalog::*; use crate::entity::{ endpoint as db_endpoint, diff --git a/crates/catalog-sql/src/service.rs b/crates/catalog-sql/src/service.rs index a0359f7e..4e335125 100644 --- a/crates/catalog-sql/src/service.rs +++ b/crates/catalog-sql/src/service.rs @@ -15,10 +15,8 @@ use serde_json::Value; use tracing::error; -use openstack_keystone_core::catalog::{ - CatalogProviderError, - types::{Service, ServiceBuilder}, -}; +use openstack_keystone_core::catalog::CatalogProviderError; +use openstack_keystone_core_types::catalog::*; use crate::entity::service as db_service; diff --git a/crates/catalog-sql/src/service/get.rs b/crates/catalog-sql/src/service/get.rs index a1147982..5a8f98ea 100644 --- a/crates/catalog-sql/src/service/get.rs +++ b/crates/catalog-sql/src/service/get.rs @@ -14,8 +14,9 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; -use openstack_keystone_core::catalog::{CatalogProviderError, types::Service}; +use openstack_keystone_core::catalog::CatalogProviderError; use openstack_keystone_core::error::DbContextExt; +use openstack_keystone_core_types::catalog::Service; use crate::entity::prelude::Service as DbService; diff --git a/crates/catalog-sql/src/service/list.rs b/crates/catalog-sql/src/service/list.rs index b7d8761f..781353d2 100644 --- a/crates/catalog-sql/src/service/list.rs +++ b/crates/catalog-sql/src/service/list.rs @@ -16,11 +16,9 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use sea_orm::query::*; -use openstack_keystone_core::catalog::{ - CatalogProviderError, - types::{Service, ServiceListParameters}, -}; +use openstack_keystone_core::catalog::CatalogProviderError; use openstack_keystone_core::error::DbContextExt; +use openstack_keystone_core_types::catalog::*; use crate::entity::{prelude::Service as DbService, service as db_service}; diff --git a/crates/core-types/Cargo.toml b/crates/core-types/Cargo.toml new file mode 100644 index 00000000..6be29dd1 --- /dev/null +++ b/crates/core-types/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "openstack-keystone-core-types" +description = "OpenStack Keystone service core types" +version = "0.1.1" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +base64.workspace = true +chrono = { workspace = true, features = ["serde", "now"] } +derive_builder.workspace = true +eyre.workspace = true +secrecy = { workspace = true, features = ["serde"] } +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +thiserror.workspace = true +tracing.workspace = true +url = { workspace = true, features = ["serde"] } +uuid.workspace = true +validator = { workspace = true, features = ["derive"] } + +[dev-dependencies] +url.workspace = true + +[features] +default = [] +bench_internals = [] diff --git a/crates/core/src/application_credential/types.rs b/crates/core-types/src/application_credential.rs similarity index 88% rename from crates/core/src/application_credential/types.rs rename to crates/core-types/src/application_credential.rs index eed2641d..d9028138 100644 --- a/crates/core/src/application_credential/types.rs +++ b/crates/core-types/src/application_credential.rs @@ -1,7 +1,6 @@ // 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 @@ -11,11 +10,12 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 -//! # Application credential related types + +//! # Application credentials provider mod access_rule; mod application_credential; -mod provider_api; +mod error; pub use access_rule::*; pub use application_credential::*; -pub use provider_api::*; +pub use error::*; diff --git a/crates/core/src/application_credential/types/access_rule.rs b/crates/core-types/src/application_credential/access_rule.rs similarity index 100% rename from crates/core/src/application_credential/types/access_rule.rs rename to crates/core-types/src/application_credential/access_rule.rs diff --git a/crates/core/src/application_credential/types/application_credential.rs b/crates/core-types/src/application_credential/application_credential.rs similarity index 99% rename from crates/core/src/application_credential/types/application_credential.rs rename to crates/core-types/src/application_credential/application_credential.rs index eb1f958c..7b908d9b 100644 --- a/crates/core/src/application_credential/types/application_credential.rs +++ b/crates/core-types/src/application_credential/application_credential.rs @@ -21,7 +21,7 @@ use validator::Validate; use super::{AccessRule, AccessRuleCreate}; use crate::error::BuilderError; -use crate::role::types::RoleRef; +use crate::role::RoleRef; /// The application credential object. #[derive(Builder, Clone, Debug, PartialEq, Serialize, Validate)] diff --git a/crates/core-types/src/application_credential/error.rs b/crates/core-types/src/application_credential/error.rs new file mode 100644 index 00000000..553acd3a --- /dev/null +++ b/crates/core-types/src/application_credential/error.rs @@ -0,0 +1,100 @@ +// 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 +//! # Application credential provider error. +use thiserror::Error; + +use crate::error::BuilderError; +use crate::role::RoleProviderError; + +/// Application credential provider error. +#[derive(Error, Debug)] +pub enum ApplicationCredentialProviderError { + /// AccessRule with matching ID and another one matching rest of parameters + /// is found. + #[error("more than one access rule matching the ID and parameters found")] + AccessRuleConflict, + + /// Conflict. + #[error("conflict: {0}")] + Conflict(String), + + /// Driver error. + #[error("backend driver error: {0}")] + Driver(String), + + /// DateTime parsing error. + #[error("error parsing int column as datetime: {expires_at}")] + ExpirationDateTimeParse { id: String, expires_at: i64 }, + + /// Password hashing error. + #[error("{}", source)] + PasswordHash { + /// The source of the error. + #[source] + source: Box, + }, + + /// Role Database error. + #[error(transparent)] + Role { + /// The source of the error. + #[from] + source: RoleProviderError, + }, + + /// Referred role not found. + #[error("role {0} not found")] + RoleNotFound(String), + + /// Secret is missing. + #[error("secret missing")] + SecretMissing, + + /// (de)serialization error. + #[error(transparent)] + Serde { + #[from] + source: serde_json::Error, + }, + + /// Structures builder error. + #[error(transparent)] + StructBuilder { + /// The source of the error. + #[from] + source: BuilderError, + }, + /// Unsupported driver. + #[error("unsupported driver `{0}` for the application credential provider")] + UnsupportedDriver(String), + + /// Request validation error. + #[error("request validation error: {}", source)] + Validation { + /// The source of the error. + #[from] + source: validator::ValidationErrors, + }, +} + +impl ApplicationCredentialProviderError { + pub fn password_hash(source: E) -> Self + where + E: std::error::Error + Send + Sync + 'static, + { + Self::PasswordHash { + source: Box::new(source), + } + } +} diff --git a/crates/core/src/trust/api.rs b/crates/core-types/src/assignment.rs similarity index 86% rename from crates/core/src/trust/api.rs rename to crates/core-types/src/assignment.rs index aaa7e745..d20a9fa5 100644 --- a/crates/core/src/trust/api.rs +++ b/crates/core-types/src/assignment.rs @@ -1,7 +1,6 @@ // 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 @@ -11,7 +10,9 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 -//! # Trust API +//! # Assignments provider +mod assignment; +mod error; -pub mod error; -pub mod types; +pub use assignment::*; +pub use error::*; diff --git a/crates/core/src/assignment/types/assignment.rs b/crates/core-types/src/assignment/assignment.rs similarity index 93% rename from crates/core/src/assignment/types/assignment.rs rename to crates/core-types/src/assignment/assignment.rs index 2320afb6..828cc809 100644 --- a/crates/core/src/assignment/types/assignment.rs +++ b/crates/core-types/src/assignment/assignment.rs @@ -18,8 +18,6 @@ use serde::Serialize; use std::fmt; use validator::Validate; -use crate::assignment::AssignmentProviderError; - /// The assignment object. #[derive(Builder, Clone, Debug, Eq, Hash, PartialEq, Serialize, Validate)] #[builder(build_fn(error = "BuilderError"))] @@ -202,21 +200,6 @@ impl fmt::Display for AssignmentType { } } -impl TryFrom<&str> for AssignmentType { - type Error = AssignmentProviderError; - fn try_from(value: &str) -> Result { - match value { - "GroupDomain" => Ok(Self::GroupDomain), - "GroupProject" => Ok(Self::GroupProject), - "GroupSystem" => Ok(Self::GroupSystem), - "UserDomain" => Ok(Self::UserDomain), - "UserProject" => Ok(Self::UserProject), - "UserSystem" => Ok(Self::UserSystem), - _ => Err(AssignmentProviderError::InvalidAssignmentType(value.into())), - } - } -} - /// Parameters for listing role assignments for role/target/actor. #[derive(Builder, Clone, Debug, Default, PartialEq, Validate)] #[builder(build_fn(error = "BuilderError"))] diff --git a/crates/core-types/src/assignment/error.rs b/crates/core-types/src/assignment/error.rs new file mode 100644 index 00000000..21559893 --- /dev/null +++ b/crates/core-types/src/assignment/error.rs @@ -0,0 +1,99 @@ +// 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 +//! # Assignment provider error types +use thiserror::Error; + +use crate::identity::IdentityProviderError; +use crate::resource::ResourceProviderError; +use crate::revoke::RevokeProviderError; +use crate::role::RoleProviderError; + +/// Assignment provider error. +#[derive(Error, Debug)] +pub enum AssignmentProviderError { + /// Assignment not found. + #[error("assignment not found: {0}")] + AssignmentNotFound(String), + + /// Conflict. + #[error("conflict: {0}")] + Conflict(String), + + /// Driver error. + #[error("backend driver error: {0}")] + Driver(String), + + /// Identity provider error. + #[error(transparent)] + IdentityProvider { + #[from] + source: IdentityProviderError, + }, + + /// Invalid assignment type. + #[error("{0}")] + InvalidAssignmentType(String), + + /// Resource provider error. + #[error(transparent)] + ResourceProvider { + #[from] + source: ResourceProviderError, + }, + + /// Revoke provider error. + #[error(transparent)] + RevokeProvider { + #[from] + source: RevokeProviderError, + }, + + /// Role not found. + #[error("role {0} not found")] + RoleNotFound(String), + + /// Role provider error. + #[error(transparent)] + RoleProvider { + #[from] + source: RoleProviderError, + }, + + /// (de)serialize error. + #[error(transparent)] + Serde { + #[from] + source: serde_json::Error, + }, + + /// Structures builder error. + #[error(transparent)] + StructBuilder { + /// The source of the error. + #[from] + source: crate::error::BuilderError, + }, + + /// Unsupported driver. + #[error("unsupported driver `{0}` for the assignment provider")] + UnsupportedDriver(String), + + /// Validation error. + #[error("request validation error: {}", source)] + Validation { + /// The source of the error. + #[from] + source: validator::ValidationErrors, + }, +} diff --git a/crates/core/src/auth/mod.rs b/crates/core-types/src/auth.rs similarity index 95% rename from crates/core/src/auth/mod.rs rename to crates/core-types/src/auth.rs index 8f1238ad..83796006 100644 --- a/crates/core/src/auth/mod.rs +++ b/crates/core-types/src/auth.rs @@ -26,14 +26,13 @@ use derive_builder::Builder; use thiserror::Error; use tracing::warn; -use crate::application_credential::types::ApplicationCredential; +use crate::application_credential::ApplicationCredential; use crate::error::BuilderError; -use crate::identity::types::{Group, UserResponse}; -use crate::resource::types::{Domain, Project}; -use crate::trust::types::Trust; +use crate::identity::{Group, UserResponse}; +use crate::resource::{Domain, Project}; +use crate::trust::Trust; #[derive(Error, Debug)] -#[non_exhaustive] pub enum AuthenticationError { /// Domain is disabled. #[error("The domain is disabled.")] @@ -207,9 +206,7 @@ impl AuthzInfo { mod tests { use super::*; - use tracing_test::traced_test; - - use crate::identity::types::{UserOptions, UserResponse}; + use crate::identity::{UserOptions, UserResponse}; #[test] fn test_authn_validate_no_user() { @@ -221,7 +218,6 @@ mod tests { } #[test] - #[traced_test] fn test_authn_validate_user_disabled() { let authn = AuthenticatedInfo::builder() .user_id("uid") @@ -246,7 +242,6 @@ mod tests { } #[test] - #[traced_test] fn test_authn_validate_user_mismatch() { let authn = AuthenticatedInfo::builder() .user_id("uid1") @@ -270,7 +265,6 @@ mod tests { } #[test] - #[traced_test] fn test_authz_validate_project() { let authz = AuthzInfo::Project(Project { id: "pid".into(), @@ -282,7 +276,6 @@ mod tests { } #[test] - #[traced_test] fn test_authz_validate_project_disabled() { let authz = AuthzInfo::Project(Project { id: "pid".into(), @@ -297,7 +290,6 @@ mod tests { } #[test] - #[traced_test] fn test_authz_validate_domain() { let authz = AuthzInfo::Domain(Domain { id: "id".into(), @@ -309,7 +301,6 @@ mod tests { } #[test] - #[traced_test] fn test_authz_validate_domain_disabled() { let authz = AuthzInfo::Domain(Domain { id: "id".into(), @@ -324,14 +315,12 @@ mod tests { } #[test] - #[traced_test] fn test_authz_validate_system() { let authz = AuthzInfo::System; assert!(authz.validate().is_ok()); } #[test] - #[traced_test] fn test_authz_validate_unscoped() { let authz = AuthzInfo::Unscoped; assert!(authz.validate().is_ok()); diff --git a/crates/core-types/src/catalog.rs b/crates/core-types/src/catalog.rs new file mode 100644 index 00000000..b3e64780 --- /dev/null +++ b/crates/core-types/src/catalog.rs @@ -0,0 +1,21 @@ +// 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 +//! # Catalog provider +mod endpoint; +mod error; +mod service; + +pub use endpoint::*; +pub use error::*; +pub use service::*; diff --git a/crates/core/src/catalog/types/endpoint.rs b/crates/core-types/src/catalog/endpoint.rs similarity index 100% rename from crates/core/src/catalog/types/endpoint.rs rename to crates/core-types/src/catalog/endpoint.rs diff --git a/crates/core-types/src/catalog/error.rs b/crates/core-types/src/catalog/error.rs new file mode 100644 index 00000000..c73e5e53 --- /dev/null +++ b/crates/core-types/src/catalog/error.rs @@ -0,0 +1,49 @@ +// 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 + +use thiserror::Error; + +use crate::error::BuilderError; + +#[derive(Error, Debug)] +pub enum CatalogProviderError { + /// Conflict. + #[error("conflict: {0}")] + Conflict(String), + + /// Driver error. + #[error("backend driver error: {0}")] + Driver(String), + + #[error("data serialization error")] + Serde { + #[from] + source: serde_json::Error, + }, + /// The service has not been found. + #[error("service {0} not found")] + ServiceNotFound(String), + + /// Structures builder error. + #[error(transparent)] + StructBuilder { + /// The source of the error. + #[from] + source: BuilderError, + }, + + /// Unsupported driver. + #[error("unsupported driver `{0}` for the catalog provider.")] + UnsupportedDriver(String), +} diff --git a/crates/core/src/catalog/types/service.rs b/crates/core-types/src/catalog/service.rs similarity index 100% rename from crates/core/src/catalog/types/service.rs rename to crates/core-types/src/catalog/service.rs diff --git a/crates/core-types/src/error.rs b/crates/core-types/src/error.rs new file mode 100644 index 00000000..7587b791 --- /dev/null +++ b/crates/core-types/src/error.rs @@ -0,0 +1,190 @@ +// 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 +//! # Error +//! +//! Diverse errors that can occur during the Keystone processing (not the API). +use thiserror::Error; + +use crate::application_credential::ApplicationCredentialProviderError; +use crate::assignment::AssignmentProviderError; +use crate::catalog::CatalogProviderError; +use crate::federation::FederationProviderError; +use crate::identity::IdentityProviderError; +use crate::identity_mapping::IdentityMappingProviderError; +use crate::k8s_auth::K8sAuthProviderError; +use crate::resource::ResourceProviderError; +use crate::revoke::RevokeProviderError; +use crate::role::RoleProviderError; +use crate::token::TokenProviderError; +use crate::trust::TrustProviderError; + +/// Builder error. +/// +/// A wrapper error that is used instead of the error generated by the +/// `derive_builder`. +#[derive(Debug, Error)] +#[non_exhaustive] +pub enum BuilderError { + /// Uninitialized field. + #[error("{0}")] + UninitializedField(String), + /// Custom validation error. + #[error("{0}")] + Validation(String), +} + +impl From for BuilderError { + fn from(s: String) -> Self { + Self::Validation(s) + } +} + +impl From for BuilderError { + fn from(ufe: derive_builder::UninitializedFieldError) -> Self { + Self::UninitializedField(ufe.to_string()) + } +} + +/// Keystone error. +#[derive(Debug, Error)] +pub enum KeystoneError { + /// Application credential provider. + #[error(transparent)] + ApplicationCredential { + /// The source of the error. + #[from] + source: ApplicationCredentialProviderError, + }, + + /// Assignment provider. + #[error(transparent)] + AssignmentProvider { + /// The source of the error. + #[from] + source: AssignmentProviderError, + }, + + /// Catalog provider. + #[error(transparent)] + CatalogProvider { + /// The source of the error. + #[from] + source: CatalogProviderError, + }, + + /// Federation provider. + #[error(transparent)] + FederationProvider { + /// The source of the error. + #[from] + source: FederationProviderError, + }, + + /// Identity provider. + #[error(transparent)] + IdentityProvider { + /// The source of the error. + #[from] + source: IdentityProviderError, + }, + + /// Identity mapping provider. + #[error(transparent)] + IdentityMapping { + /// The source of the error. + #[from] + source: IdentityMappingProviderError, + }, + + /// IO error. + #[error(transparent)] + IO { + /// The source of the error. + #[from] + source: std::io::Error, + }, + + /// Json serialization error. + #[error("json serde error: {}", source)] + Json { + /// The source of the error. + #[from] + source: serde_json::Error, + }, + + /// K8s auth provider. + #[error(transparent)] + K8sAuthProvider { + /// The source of the error. + #[from] + source: K8sAuthProviderError, + }, + + /// Policy engine is not available. + #[error("policy enforcement is requested, but not available with the enabled features")] + PolicyEnforcementNotAvailable, + + /// Resource provider. + #[error(transparent)] + ResourceProvider { + /// The source of the error. + #[from] + source: ResourceProviderError, + }, + + /// Revoke provider error. + #[error(transparent)] + RevokeProvider { + /// The source of the error. + #[from] + source: RevokeProviderError, + }, + + /// Role provider. + #[error(transparent)] + RoleProvider { + /// The source of the error. + #[from] + source: RoleProviderError, + }, + + /// Token provider. + #[error(transparent)] + TokenProvider { + /// The source of the error. + #[from] + source: TokenProviderError, + }, + + /// Trust provider. + #[error(transparent)] + TrustProvider { + /// The source of the error. + #[from] + source: TrustProviderError, + }, + + /// Url parsing error. + #[error(transparent)] + UrlParse { + #[from] + source: url::ParseError, + }, + + #[error("provider error: {}", source)] + Provider { + #[source] + source: Box, + }, +} diff --git a/crates/core-types/src/federation.rs b/crates/core-types/src/federation.rs new file mode 100644 index 00000000..4a9a6978 --- /dev/null +++ b/crates/core-types/src/federation.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 +//! # Federation provider +mod auth_state; +mod error; +mod identity_provider; +mod mapping; + +pub use auth_state::*; +pub use error::*; +pub use identity_provider::*; +pub use mapping::*; diff --git a/crates/core/src/federation/types/auth_state.rs b/crates/core-types/src/federation/auth_state.rs similarity index 97% rename from crates/core/src/federation/types/auth_state.rs rename to crates/core-types/src/federation/auth_state.rs index 44228827..24c6edf1 100644 --- a/crates/core/src/federation/types/auth_state.rs +++ b/crates/core-types/src/federation/auth_state.rs @@ -15,8 +15,8 @@ use chrono::{DateTime, Utc}; use derive_builder::Builder; -use crate::common::types::Scope; use crate::error::BuilderError; +use crate::scope::Scope; #[derive(Builder, Clone, Debug, Default, PartialEq)] #[builder(build_fn(error = "BuilderError"))] diff --git a/crates/core-types/src/federation/error.rs b/crates/core-types/src/federation/error.rs new file mode 100644 index 00000000..e0a8cb8a --- /dev/null +++ b/crates/core-types/src/federation/error.rs @@ -0,0 +1,67 @@ +// 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 provider error +use thiserror::Error; + +use crate::error::BuilderError; + +/// Federation provider error. +#[derive(Error, Debug)] +pub enum FederationProviderError { + #[error("authentication state is not found")] + AuthStateNotFound(String), + + /// Conflict. + #[error("conflict: {0}")] + Conflict(String), + + /// Driver error. + #[error("backend driver error: {0}")] + Driver(String), + + /// IDP not found. + #[error("identity provider {0} not found")] + IdentityProviderNotFound(String), + + /// Mapping not found. + #[error("mapping {0} not found")] + MappingNotFound(String), + + /// Use of token_project_id requires domain_id to be set. + #[error("`mapping.domain_id` must be set")] + MappingTokenProjectDomainUnset, + + /// Use of token_user_id requires domain_id to be set. + #[error("`mapping.domain_id` must be set")] + MappingTokenUserDomainUnset, + + /// Identity provider error. + #[error("data serialization error")] + Serde { + #[from] + source: serde_json::Error, + }, + + /// Structures builder error. + #[error(transparent)] + StructBuilder { + /// The source of the error. + #[from] + source: BuilderError, + }, + + /// Unsupported driver. + #[error("unsupported driver `{0}` for the federation provider")] + UnsupportedDriver(String), +} diff --git a/crates/core/src/federation/types/identity_provider.rs b/crates/core-types/src/federation/identity_provider.rs similarity index 100% rename from crates/core/src/federation/types/identity_provider.rs rename to crates/core-types/src/federation/identity_provider.rs diff --git a/crates/core/src/federation/types/mapping.rs b/crates/core-types/src/federation/mapping.rs similarity index 100% rename from crates/core/src/federation/types/mapping.rs rename to crates/core-types/src/federation/mapping.rs diff --git a/crates/core/src/federation/types.rs b/crates/core-types/src/federation/types.rs similarity index 100% rename from crates/core/src/federation/types.rs rename to crates/core-types/src/federation/types.rs diff --git a/crates/core/src/identity/types.rs b/crates/core-types/src/identity.rs similarity index 85% rename from crates/core/src/identity/types.rs rename to crates/core-types/src/identity.rs index f30e5391..1ac489d2 100644 --- a/crates/core/src/identity/types.rs +++ b/crates/core-types/src/identity.rs @@ -12,12 +12,14 @@ // // SPDX-License-Identifier: Apache-2.0 -pub mod group; -pub mod provider_api; -pub mod service_account; -pub mod user; +//! # Identity provider +mod error; +mod group; +mod service_account; +mod user; + +pub use error::*; pub use group::*; -pub use provider_api::IdentityApi; pub use service_account::*; pub use user::*; diff --git a/crates/core-types/src/identity/error.rs b/crates/core-types/src/identity/error.rs new file mode 100644 index 00000000..8de47a8d --- /dev/null +++ b/crates/core-types/src/identity/error.rs @@ -0,0 +1,138 @@ +// 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 + +use thiserror::Error; + +use crate::auth::AuthenticationError; +use crate::error::BuilderError; +use crate::resource::ResourceProviderError; + +/// Identity provider error. +#[derive(Error, Debug)] +pub enum IdentityProviderError { + /// Authentication error. + #[error(transparent)] + Authentication { + #[from] + source: AuthenticationError, + }, + + /// Conflict. + #[error("conflict: {0}")] + Conflict(String), + + #[error("Date calculation error")] + DateError, + + /// Driver error. + #[error("backend driver error: {0}")] + Driver(String), + + /// The group has not been found. + #[error("group {0} not found")] + GroupNotFound(String), + + #[error("{}", source)] + Join { + #[source] + source: Box, + }, + + #[error("corrupted database entries for user {0}")] + MalformedUser(String), + + /// No data for local_user and passwords. + #[error("no passwords for the user {0}")] + NoPasswordsForUser(String), + + /// Row does not contain password hash. + #[error("no passwords hash on the row id: {0}")] + NoPasswordHash(String), + + /// No entry in the `user` table for the user. + #[error("no entry in the `user` table found for user_id: {0}")] + NoMainUserEntry(String), + + /// Password hashing error. + #[error("{}", source)] + PasswordHash { + #[source] + source: Box, + }, + + /// Resource provider error. + #[error(transparent)] + ResourceProvider { + #[from] + source: ResourceProviderError, + }, + + /// (de)serialization error. + #[error("data serialization error")] + Serde { + #[from] + source: serde_json::Error, + }, + + /// Structures builder error. + #[error(transparent)] + StructBuilder { + /// The source of the error. + #[from] + source: BuilderError, + }, + + /// Unsupported driver. + #[error("unsupported driver `{0}` for the identity provider")] + UnsupportedDriver(String), + + #[error("user id must be given")] + UserIdMissing, + + /// User ID or Name with Domain must be specified. + #[error("either user id or user name with user domain id or name must be given")] + UserIdOrNameWithDomain, + + /// The user has not been found. + #[error("user {0} not found")] + UserNotFound(String), + + /// Request validation error. + #[error("request validation error: {}", source)] + Validation { + /// The source of the error. + #[from] + source: validator::ValidationErrors, + }, +} + +impl IdentityProviderError { + pub fn password_hash(source: E) -> Self + where + E: std::error::Error + Send + Sync + 'static, + { + Self::PasswordHash { + source: Box::new(source), + } + } + + pub fn join(source: E) -> Self + where + E: std::error::Error + Send + Sync + 'static, + { + Self::Join { + source: Box::new(source), + } + } +} diff --git a/crates/core/src/identity/types/group.rs b/crates/core-types/src/identity/group.rs similarity index 100% rename from crates/core/src/identity/types/group.rs rename to crates/core-types/src/identity/group.rs diff --git a/crates/core/src/identity/types/service_account.rs b/crates/core-types/src/identity/service_account.rs similarity index 100% rename from crates/core/src/identity/types/service_account.rs rename to crates/core-types/src/identity/service_account.rs diff --git a/crates/core/src/identity/types/user.rs b/crates/core-types/src/identity/user.rs similarity index 87% rename from crates/core/src/identity/types/user.rs rename to crates/core-types/src/identity/user.rs index 32ae01e1..b49e2cfd 100644 --- a/crates/core/src/identity/types/user.rs +++ b/crates/core-types/src/identity/user.rs @@ -12,14 +12,12 @@ // // SPDX-License-Identifier: Apache-2.0 -use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc}; +use chrono::{DateTime, Utc}; use derive_builder::Builder; use serde::Serialize; use serde_json::Value; use validator::Validate; -use openstack_keystone_config::Config; - use crate::error::BuilderError; #[derive(Builder, Clone, Debug, PartialEq, Serialize, Validate)] @@ -312,45 +310,3 @@ pub struct Domain { #[validate(length(max = 255))] pub name: Option, } - -/// Calculate the `last_active_at` for the user entry. -pub fn get_user_last_active_at( - conf: &Config, - enabled: Option, - activity_date: NaiveDateTime, -) -> Option { - if enabled.is_some_and(|x| x) { - if conf - .security_compliance - .disable_user_account_days_inactive - .is_some() - { - Some(activity_date.date()) - } else { - None - } - } else { - None - } -} - -#[cfg(test)] -pub mod tests { - use super::*; - #[test] - fn test_get_user_last_active_at() { - let now = Utc::now().naive_utc(); - let mut cfg = Config::default(); - assert!(get_user_last_active_at(&cfg, Some(false), now).is_none()); - assert!(get_user_last_active_at(&cfg, Some(true), now).is_none()); - assert!(get_user_last_active_at(&cfg, None, now).is_none()); - - cfg.security_compliance.disable_user_account_days_inactive = Some(1); - assert_eq!( - get_user_last_active_at(&cfg, Some(true), now), - Some(now.date()) - ); - assert!(get_user_last_active_at(&cfg, Some(false), now).is_none()); - assert!(get_user_last_active_at(&cfg, None, now).is_none()); - } -} diff --git a/crates/core/src/identity_mapping/types.rs b/crates/core-types/src/identity_mapping.rs similarity index 88% rename from crates/core/src/identity_mapping/types.rs rename to crates/core-types/src/identity_mapping.rs index c4568613..b58cedfa 100644 --- a/crates/core/src/identity_mapping/types.rs +++ b/crates/core-types/src/identity_mapping.rs @@ -12,8 +12,10 @@ // // SPDX-License-Identifier: Apache-2.0 -pub mod id_mapping; -pub mod provider_api; +//! # Identity mapping provider +mod error; +mod id_mapping; + +pub use error::*; pub use id_mapping::*; -pub use provider_api::IdentityMappingApi; diff --git a/crates/core-types/src/identity_mapping/error.rs b/crates/core-types/src/identity_mapping/error.rs new file mode 100644 index 00000000..8597e44e --- /dev/null +++ b/crates/core-types/src/identity_mapping/error.rs @@ -0,0 +1,57 @@ +// 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 + +use thiserror::Error; + +//use crate::api::error::KeystoneApiError; +use crate::error::BuilderError; + +/// Identity mapping provider error. +#[derive(Error, Debug)] +pub enum IdentityMappingProviderError { + /// Conflict. + #[error("conflict: {0}")] + Conflict(String), + + /// Driver error. + #[error("backend driver error: {0}")] + Driver(String), + + /// (de)serialization error. + #[error("data serialization error")] + Serde { + #[from] + source: serde_json::Error, + }, + + /// Structures builder error. + #[error(transparent)] + StructBuilder { + /// The source of the error. + #[from] + source: BuilderError, + }, + + /// Unsupported driver. + #[error("unsupported driver `{0}` for the identity mapping provider")] + UnsupportedDriver(String), + + /// Request validation error. + #[error("request validation error: {}", source)] + Validation { + /// The source of the error. + #[from] + source: validator::ValidationErrors, + }, +} diff --git a/crates/core/src/identity_mapping/types/id_mapping.rs b/crates/core-types/src/identity_mapping/id_mapping.rs similarity index 100% rename from crates/core/src/identity_mapping/types/id_mapping.rs rename to crates/core-types/src/identity_mapping/id_mapping.rs diff --git a/crates/core-types/src/k8s_auth.rs b/crates/core-types/src/k8s_auth.rs new file mode 100644 index 00000000..bde8e632 --- /dev/null +++ b/crates/core-types/src/k8s_auth.rs @@ -0,0 +1,24 @@ +// 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 +//! # Kubernetes authentication. + +mod auth; +mod error; +mod instance; +mod role; + +pub use auth::*; +pub use error::*; +pub use instance::*; +pub use role::*; diff --git a/crates/core/src/k8s_auth/types/auth.rs b/crates/core-types/src/k8s_auth/auth.rs similarity index 82% rename from crates/core/src/k8s_auth/types/auth.rs rename to crates/core-types/src/k8s_auth/auth.rs index 283f332a..8279cd25 100644 --- a/crates/core/src/k8s_auth/types/auth.rs +++ b/crates/core-types/src/k8s_auth/auth.rs @@ -15,7 +15,6 @@ use derive_builder::Builder; use secrecy::SecretString; -use serde::{Deserialize, Serialize}; use crate::error::BuilderError; @@ -31,11 +30,3 @@ pub struct K8sAuthRequest { pub role_name: String, } - -/// K8s JWT claims. -#[derive(Debug, Deserialize, Serialize)] -pub(crate) struct K8sClaims { - pub(crate) aud: Vec, - pub(crate) exp: u64, - pub(crate) sub: String, -} diff --git a/crates/core-types/src/k8s_auth/error.rs b/crates/core-types/src/k8s_auth/error.rs new file mode 100644 index 00000000..b9f75d9b --- /dev/null +++ b/crates/core-types/src/k8s_auth/error.rs @@ -0,0 +1,195 @@ +// 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 +//! # K8s Auth error + +use thiserror::Error; + +use crate::error::BuilderError; +use crate::identity::IdentityProviderError; +use crate::token::TokenProviderError; + +/// K8s auth provider error. +#[derive(Error, Debug)] +#[non_exhaustive] +pub enum K8sAuthProviderError { + /// Role audience does not match. + #[error("role `bound_audience` does not match")] + AudienceMismatch, + + /// K8s auth instance disabled. + #[error("k8s instance {0} not active")] + AuthInstanceNotActive(String), + + /// K8s auth instance not found. + #[error("k8s instance {0} not found")] + AuthInstanceNotFound(String), + + /// K8s CA certificate is unknown. + #[error("CA certificate of the k8s cannot be identified")] + CaCertificateUnknown, + + /// Conflict. + #[error("conflict: {0}")] + Conflict(String), + + /// Driver error. + #[error("backend driver error: {source}")] + Driver { + /// The source of the error. + #[source] + source: Box, + }, + + /// Service account name of the token not matching the + /// `bound_service_account_names`. + #[error("invalid service account name of the token")] + FailedBoundServiceAccountName(String), + + /// Service account name of the token not matching the + /// `bound_service_account_namespaces`. + #[error("invalid service account namespace of the token")] + FailedBoundServiceAccountNamespace(String), + + /// JWT error. + #[error("jwt validation error: {source}")] + Jwt { + /// The source of the error. + #[source] + source: Box, + }, + + /// Expired token. + #[error("expired token")] + ExpiredToken, + + /// Http client error. + #[error("{}", source)] + Http { + /// The source of the error. + #[source] + source: Box, + }, + + /// Identity provider error. + #[error(transparent)] + IdentityProvider { + /// The source of the error. + #[from] + source: Box, + }, + + /// Insecure JWT signature algorithm. + #[error("insecure jwt signature algorithm")] + InsecureAlgorithm, + + /// Invalid token. + #[error("invalid token")] + InvalidToken, + + /// Invalid token review response. + #[error("invalid token review response")] + InvalidTokenReviewResponse, + + /// K8s auth role not found. + #[error("k8s auth role {0} not found")] + RoleNotFound(String), + + /// K8s auth role not active. + #[error("k8s auth role {0} not active")] + RoleNotActive(String), + + /// Role is bound to the other configuration. + #[error("k8s auth role {0} belongs to the other instance")] + RoleInstanceOwnershipMismatch(String), + + /// Structures builder error. + #[error(transparent)] + StructBuilder { + /// The source of the error. + #[from] + source: Box, + }, + + /// Token provider error. + #[error(transparent)] + TokenProvider { + /// The source of the error. + #[from] + source: Box, + }, + + /// Token restriction not found. + #[error("token restriction {0} not found")] + TokenRestrictionNotFound(String), + + /// Token restriction MUST specify the `project_id`. + #[error("token restriction must specify `project_id`")] + TokenRestrictionMustSpecifyProjectId, + + /// Token restriction MUST specify the `user_id`. + #[error("token restriction must specify `user_id`")] + TokenRestrictionMustSpecifyUserId, + + /// Unsupported driver. + #[error("unsupported driver `{0}` for the k8s provider")] + UnsupportedDriver(String), + + /// User not found. + #[error("user {0} not found")] + UserNotFound(String), +} + +impl K8sAuthProviderError { + pub fn jwt(source: E) -> Self + where + E: std::error::Error + Send + Sync + 'static, + { + Self::Jwt { + source: Box::new(source), + } + } + + pub fn http(source: E) -> Self + where + E: std::error::Error + Send + Sync + 'static, + { + Self::Http { + source: Box::new(source), + } + } +} + +impl From for K8sAuthProviderError { + fn from(value: TokenProviderError) -> Self { + Self::TokenProvider { + source: Box::new(value), + } + } +} + +impl From for K8sAuthProviderError { + fn from(value: BuilderError) -> Self { + Self::StructBuilder { + source: Box::new(value), + } + } +} + +impl From for K8sAuthProviderError { + fn from(value: IdentityProviderError) -> Self { + Self::IdentityProvider { + source: Box::new(value), + } + } +} diff --git a/crates/core/src/k8s_auth/types/instance.rs b/crates/core-types/src/k8s_auth/instance.rs similarity index 100% rename from crates/core/src/k8s_auth/types/instance.rs rename to crates/core-types/src/k8s_auth/instance.rs diff --git a/crates/core/src/k8s_auth/types/role.rs b/crates/core-types/src/k8s_auth/role.rs similarity index 100% rename from crates/core/src/k8s_auth/types/role.rs rename to crates/core-types/src/k8s_auth/role.rs diff --git a/crates/core/src/trust/api/types.rs b/crates/core-types/src/lib.rs similarity index 63% rename from crates/core/src/trust/api/types.rs rename to crates/core-types/src/lib.rs index dc5e78f3..d35eb1ba 100644 --- a/crates/core/src/trust/api/types.rs +++ b/crates/core-types/src/lib.rs @@ -11,6 +11,24 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 -//! # Trust API +//! # OpenStack Keystone core provider types +//! + +#![allow(clippy::module_inception)] + +pub mod application_credential; +pub mod assignment; +pub mod auth; +pub mod catalog; +pub mod error; +pub mod federation; +pub mod identity; +pub mod identity_mapping; +pub mod k8s_auth; +pub mod resource; +pub mod revoke; +pub mod role; +pub mod scope; +pub mod token; pub mod trust; diff --git a/crates/core/src/assignment/types.rs b/crates/core-types/src/resource.rs similarity index 83% rename from crates/core/src/assignment/types.rs rename to crates/core-types/src/resource.rs index 5145124e..46c5b5cf 100644 --- a/crates/core/src/assignment/types.rs +++ b/crates/core-types/src/resource.rs @@ -11,9 +11,11 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 +//! # Resource provider +mod domain; +mod error; +mod project; -pub mod assignment; -pub mod provider_api; - -pub use crate::assignment::types::assignment::*; -pub use provider_api::*; +pub use domain::*; +pub use error::*; +pub use project::*; diff --git a/crates/core/src/resource/types/domain.rs b/crates/core-types/src/resource/domain.rs similarity index 100% rename from crates/core/src/resource/types/domain.rs rename to crates/core-types/src/resource/domain.rs diff --git a/crates/core-types/src/resource/error.rs b/crates/core-types/src/resource/error.rs new file mode 100644 index 00000000..feb5da80 --- /dev/null +++ b/crates/core-types/src/resource/error.rs @@ -0,0 +1,62 @@ +// 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 + +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum ResourceProviderError { + /// Conflict. + #[error("conflict: {0}")] + Conflict(String), + + /// Domain not found. + #[error("domain {0} not found")] + DomainNotFound(String), + + /// Driver error. + #[error("backend driver error: {0}")] + Driver(String), + + /// (De)Ser error. + #[error(transparent)] + Serde { + /// The source of the error. + #[from] + source: serde_json::Error, + }, + + /// Structures builder error. + #[error(transparent)] + StructBuilder { + /// The source of the error. + #[from] + source: crate::error::BuilderError, + }, + + /// Project not found. + #[error("project {0} not found")] + ProjectNotFound(String), + + /// Unsupported driver. + #[error("unsupported driver `{0}` for the resource provider")] + UnsupportedDriver(String), + + /// Request validation error. + #[error("request validation error: {}", source)] + Validation { + /// The source of the error. + #[from] + source: validator::ValidationErrors, + }, +} diff --git a/crates/core/src/resource/types/project.rs b/crates/core-types/src/resource/project.rs similarity index 100% rename from crates/core/src/resource/types/project.rs rename to crates/core-types/src/resource/project.rs diff --git a/crates/core-types/src/revoke.rs b/crates/core-types/src/revoke.rs new file mode 100644 index 00000000..bf61315b --- /dev/null +++ b/crates/core-types/src/revoke.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 +//! # Token revocation provider. +mod error; +mod revocation_event; + +pub use error::*; +pub use revocation_event::*; diff --git a/crates/core-types/src/revoke/error.rs b/crates/core-types/src/revoke/error.rs new file mode 100644 index 00000000..e40205f0 --- /dev/null +++ b/crates/core-types/src/revoke/error.rs @@ -0,0 +1,44 @@ +// 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 +//! Token revocation errors. + +use thiserror::Error; + +/// Revoke provider error. +#[derive(Error, Debug)] +pub enum RevokeProviderError { + /// Conflict. + #[error("conflict: {0}")] + Conflict(String), + + /// Driver error. + #[error("backend driver error: {0}")] + Driver(String), + + /// Structures builder error. + #[error(transparent)] + StructBuilder { + /// The source of the error. + #[from] + source: crate::error::BuilderError, + }, + + /// No audit ID in the token. + #[error("token does not have the audit_id set")] + TokenHasNoAuditId, + + /// Unsupported driver. + #[error("unsupported driver `{0}` for the revoke provider")] + UnsupportedDriver(String), +} diff --git a/crates/core/src/revoke/types/revocation_event.rs b/crates/core-types/src/revoke/revocation_event.rs similarity index 95% rename from crates/core/src/revoke/types/revocation_event.rs rename to crates/core-types/src/revoke/revocation_event.rs index 1538576d..2b2cfc4d 100644 --- a/crates/core/src/revoke/types/revocation_event.rs +++ b/crates/core-types/src/revoke/revocation_event.rs @@ -17,8 +17,7 @@ use chrono::{DateTime, Timelike, Utc}; use derive_builder::Builder; -use crate::revoke::RevokeProviderError; -use crate::token::types::Token; +use crate::token::Token; /// Revocation event. #[derive(Builder, Clone, Debug, Default, PartialEq)] @@ -148,7 +147,7 @@ pub struct RevocationEventListParameters { // against the user_domain_id and the scope_domain_id. That means, however, that // we must resolve the user first. impl TryFrom<&Token> for RevocationEventListParameters { - type Error = RevokeProviderError; + type Error = crate::error::BuilderError; fn try_from(value: &Token) -> Result { // TODO: for trust token user_id can be trustee_id or trustor_id Ok(Self { @@ -158,7 +157,9 @@ impl TryFrom<&Token> for RevocationEventListParameters { value .audit_ids() .first() - .ok_or(RevokeProviderError::TokenHasNoAuditId)?, + .ok_or(crate::error::BuilderError::Validation( + "token has no audit_id".to_string(), + ))?, //.ok_or(RevokeProviderError::TokenHasNoAuditId)?, ) .cloned(), //consumer_id: None, @@ -203,18 +204,15 @@ impl TryFrom<&Token> for RevocationEventListParameters { /// Convert the Token into the new revocation events record following the /// . impl TryFrom<&Token> for RevocationEventCreate { - type Error = RevokeProviderError; + type Error = crate::error::BuilderError; fn try_from(value: &Token) -> Result { let now = Utc::now(); Ok(Self { access_token_id: None, audit_chain_id: None, - audit_id: Some( - value - .audit_ids() - .first() - .ok_or(RevokeProviderError::TokenHasNoAuditId)?, - ) + audit_id: Some(value.audit_ids().first().ok_or( + crate::error::BuilderError::Validation("token has no audit_id".to_string()), + )?) .cloned(), consumer_id: None, domain_id: None, @@ -236,10 +234,10 @@ impl TryFrom<&Token> for RevocationEventCreate { #[cfg(test)] mod tests { use super::*; - use crate::identity::types::UserResponseBuilder; - use crate::role::types::RoleRef; + use crate::identity::UserResponseBuilder; + use crate::role::RoleRef; use crate::token::{ProjectScopePayload, TrustPayload}; - use crate::trust::types::Trust; + use crate::trust::Trust; #[test] fn test_list_for_project_scope_token() { diff --git a/crates/core/src/federation/api/types.rs b/crates/core-types/src/role.rs similarity index 87% rename from crates/core/src/federation/api/types.rs rename to crates/core-types/src/role.rs index 7f514d46..9967f369 100644 --- a/crates/core/src/federation/api/types.rs +++ b/crates/core-types/src/role.rs @@ -1,7 +1,6 @@ // 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 @@ -11,6 +10,9 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 +//! # Role provider core types +mod error; +mod role; -pub mod identity_provider; -pub mod mapping; +pub use error::*; +pub use role::*; diff --git a/crates/core-types/src/role/error.rs b/crates/core-types/src/role/error.rs new file mode 100644 index 00000000..f3cf5658 --- /dev/null +++ b/crates/core-types/src/role/error.rs @@ -0,0 +1,58 @@ +// 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 +//! # Role provider error types +use thiserror::Error; + +/// Role provider error. +#[derive(Error, Debug)] +pub enum RoleProviderError { + /// Conflict. + #[error("conflict: {0}")] + Conflict(String), + + /// Driver error. + #[error("backend driver error: {0}")] + Driver(String), + + /// Role not found. + #[error("role {0} not found")] + RoleNotFound(String), + + /// (de)serialize error. + #[error(transparent)] + Serde { + #[from] + source: serde_json::Error, + }, + + /// Structures builder error. + #[error(transparent)] + StructBuilder { + /// The source of the error. + #[from] + source: crate::error::BuilderError, + }, + + /// Unsupported driver. + #[error("unsupported driver `{0}` for the role provider")] + UnsupportedDriver(String), + + /// Validation error. + #[error("request validation error: {}", source)] + Validation { + /// The source of the error. + #[from] + source: validator::ValidationErrors, + }, +} diff --git a/crates/core/src/role/types/role.rs b/crates/core-types/src/role/role.rs similarity index 100% rename from crates/core/src/role/types/role.rs rename to crates/core-types/src/role/role.rs diff --git a/crates/core/src/common/types.rs b/crates/core-types/src/scope.rs similarity index 98% rename from crates/core/src/common/types.rs rename to crates/core-types/src/scope.rs index a956dc93..9c1d40cb 100644 --- a/crates/core/src/common/types.rs +++ b/crates/core-types/src/scope.rs @@ -11,7 +11,7 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 -//! # Common types +//! # Common functionality use derive_builder::Builder; use serde::{Deserialize, Serialize}; use validator::Validate; diff --git a/crates/core/src/token/types.rs b/crates/core-types/src/token.rs similarity index 56% rename from crates/core/src/token/types.rs rename to crates/core-types/src/token.rs index e60aa53b..c7756410 100644 --- a/crates/core/src/token/types.rs +++ b/crates/core-types/src/token.rs @@ -12,46 +12,21 @@ // // SPDX-License-Identifier: Apache-2.0 //! Token provider types. - use chrono::{DateTime, Utc}; use serde::Serialize; use validator::Validate; -use crate::identity::{IdentityApi, types::UserResponse}; -use crate::keystone::ServiceState; -use crate::resource::{ResourceApi, types::*}; -use crate::role::types::RoleRef; -use crate::token::error::TokenProviderError; -use crate::trust::TrustApi; +use crate::identity::UserResponse; +use crate::resource::{Domain, Project}; +use crate::role::RoleRef; -pub mod application_credential; -pub mod common; -pub mod domain_scoped; -pub mod federation_domain_scoped; -pub mod federation_project_scoped; -pub mod federation_unscoped; -pub mod project_scoped; -pub mod provider_api; -pub mod restricted; -pub mod system_scoped; -pub mod trust; -pub mod unscoped; +mod error; +pub mod payload; +mod restriction; -pub use application_credential::*; -pub use domain_scoped::{DomainScopePayload, DomainScopePayloadBuilder}; -pub use federation_domain_scoped::{ - FederationDomainScopePayload, FederationDomainScopePayloadBuilder, -}; -pub use federation_project_scoped::{ - FederationProjectScopePayload, FederationProjectScopePayloadBuilder, -}; -pub use federation_unscoped::{FederationUnscopedPayload, FederationUnscopedPayloadBuilder}; -pub use project_scoped::{ProjectScopePayload, ProjectScopePayloadBuilder}; -pub use provider_api::TokenApi; -pub use restricted::*; -pub use system_scoped::*; -pub use trust::*; -pub use unscoped::*; +pub use error::*; +pub use payload::*; +pub use restriction::*; /// Fernet Token. #[derive(Clone, Debug, PartialEq, Serialize)] @@ -279,189 +254,6 @@ impl Token { _ => None, } } - - /// Validate the token scope. - /// - /// Validate the scope validity of the token scope. For a project scoped - /// tokens this will raise an error when the project is disabled. For - /// domain scoped token the domain must be active. - pub async fn validate_scope(&self, _state: &ServiceState) -> Result<(), TokenProviderError> { - match self { - Token::ApplicationCredential(data) => { - if !data - .project - .as_ref() - .ok_or(TokenProviderError::ScopeMissing)? - .enabled - { - return Err(TokenProviderError::ProjectDisabled(data.project_id.clone())); - } - if data - .application_credential - .as_ref() - .is_none_or(|ac| ac.project_id != data.project_id) - { - return Err(TokenProviderError::ApplicationCredentialScopeMismatch); - } - } - Token::DomainScope(data) => { - if !data - .domain - .as_ref() - .ok_or(TokenProviderError::ScopeMissing)? - .enabled - { - return Err(TokenProviderError::DomainDisabled(data.domain_id.clone())); - } - } - Token::FederationDomainScope(data) => { - if !data - .domain - .as_ref() - .ok_or(TokenProviderError::ScopeMissing)? - .enabled - { - return Err(TokenProviderError::DomainDisabled(data.domain_id.clone())); - } - } - Token::FederationProjectScope(data) => { - if !data - .project - .as_ref() - .ok_or(TokenProviderError::ScopeMissing)? - .enabled - { - return Err(TokenProviderError::ProjectDisabled(data.project_id.clone())); - } - } - Token::FederationUnscoped(_) => {} - Token::ProjectScope(data) => { - if !data - .project - .as_ref() - .ok_or(TokenProviderError::ScopeMissing)? - .enabled - { - return Err(TokenProviderError::ProjectDisabled(data.project_id.clone())); - } - } - Token::Restricted(data) => { - if !data - .project - .as_ref() - .ok_or(TokenProviderError::ScopeMissing)? - .enabled - { - return Err(TokenProviderError::ProjectDisabled(data.project_id.clone())); - } - } - Token::SystemScope(_data) => {} - Token::Trust(data) => { - if !data - .project - .as_ref() - .ok_or(TokenProviderError::ScopeMissing)? - .enabled - { - return Err(TokenProviderError::ProjectDisabled(data.project_id.clone())); - } - } - Token::Unscoped(_) => {} - } - Ok(()) - } - - /// Validate the token subject. - /// - /// Perform checks for the token subject: - /// - /// - user is enabled - /// - user domain is enabled - /// - application credential is not expired - pub async fn validate_subject(&self, state: &ServiceState) -> Result<(), TokenProviderError> { - let user_domain_id: String; - if let Some(user) = self.user() { - // The "user" must be active - if !user.enabled { - return Err(TokenProviderError::UserDisabled(user.id.clone())); - } - - // Ensure user domain is enabled - if !state - .provider - .get_resource_provider() - .get_domain_enabled(state, &user.domain_id) - .await? - { - return Err(TokenProviderError::UserDomainDisabled); - } - - user_domain_id = user.domain_id.clone(); - } else { - return Err(TokenProviderError::SubjectMissing); - } - - match self { - Token::ApplicationCredential(data) => { - // Check whether application credential is expired - if data - .application_credential - .as_ref() - .and_then(|ac| ac.expires_at) - .is_some_and(|expiry| expiry < Utc::now()) - { - return Err(TokenProviderError::Expired); - } - } - Token::DomainScope(_data) => {} - Token::FederationDomainScope(_data) => {} - Token::FederationProjectScope(_data) => {} - Token::FederationUnscoped(_data) => {} - Token::ProjectScope(_data) => {} - Token::Restricted(_data) => {} - Token::SystemScope(_data) => {} - Token::Trust(data) => { - // Validate the trust chain - state - .provider - .get_trust_provider() - .validate_trust_delegation_chain( - state, - data.trust - .as_ref() - .ok_or(TokenProviderError::SubjectMissing)?, - ) - .await?; - // Validate trustor and trustee - if let Some(trust) = &data.trust { - if data.user_id != trust.trustee_user_id { - return Err(TokenProviderError::UserIsNotTrustee); - } - - // Resolve and verify trustor domain is enabled - let trustor_domain_id = state - .provider - .get_identity_provider() - .get_user_domain_id(state, &trust.trustor_user_id) - .await?; - - if user_domain_id != trustor_domain_id - && !state - .provider - .get_resource_provider() - .get_domain_enabled(state, &trustor_domain_id) - .await? - { - return Err(TokenProviderError::TrustorDomainDisabled); - } - } else { - return Err(TokenProviderError::SubjectMissing); - } - } - Token::Unscoped(_data) => {} - } - Ok(()) - } } impl Validate for Token { diff --git a/crates/core-types/src/token/error.rs b/crates/core-types/src/token/error.rs new file mode 100644 index 00000000..e833537e --- /dev/null +++ b/crates/core-types/src/token/error.rs @@ -0,0 +1,182 @@ +// 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 +//! Token provider errors. + +use thiserror::Error; + +use crate::application_credential::ApplicationCredentialProviderError; +use crate::assignment::AssignmentProviderError; +use crate::auth::AuthenticationError; +use crate::error::BuilderError; +use crate::identity::IdentityProviderError; +use crate::resource::ResourceProviderError; +use crate::revoke::RevokeProviderError; +use crate::role::RoleProviderError; +use crate::trust::TrustProviderError; + +/// Token provider error. +#[derive(Error, Debug)] +#[non_exhaustive] +pub enum TokenProviderError { + /// Actor has no roles on the target scope. + #[error("actor has no roles on scope")] + ActorHasNoRolesOnTarget, + + /// Application Credential has expired. + #[error("application credential has expired")] + ApplicationCredentialExpired, + + /// Application Credential used in the token is not found. + #[error("application credential with id: {0} not found")] + ApplicationCredentialNotFound(String), + + /// Application credential provider error. + #[error(transparent)] + ApplicationCredentialProvider { + /// The source of the error. + #[from] + source: ApplicationCredentialProviderError, + }, + + /// Application Credential is bound to the other project. + #[error("application credential is bound to another project")] + ApplicationCredentialScopeMismatch, + + /// Assignment provider error. + #[error(transparent)] + AssignmentProvider { + /// The source of the error. + #[from] + source: AssignmentProviderError, + }, + + /// Authentication error. + #[error(transparent)] + Authentication(#[from] AuthenticationError), + + /// Conflict. + #[error("{message}")] + Conflict { message: String, context: String }, + + /// The domain is disabled. + #[error("domain is disabled")] + DomainDisabled(String), + + /// Driver error. + #[error("backend driver error: {source}")] + Driver { + #[source] + source: Box, + }, + + /// Expired token. + #[error("token expired")] + Expired, + + /// Expiry calculation error. + #[error("token expiry calculation failed")] + ExpiryCalculation, + + /// Federated payload missing data error. + #[error("federated payload must contain idp_id and protocol_id")] + FederatedPayloadMissingData, + + /// Identity provider error. + #[error(transparent)] + IdentityProvider(#[from] IdentityProviderError), + + /// The project is disabled. + #[error("project disabled")] + ProjectDisabled(String), + + /// Resource provider error. + #[error(transparent)] + ResourceProvider(#[from] ResourceProviderError), + + /// Restricted token project scoped error. + #[error("token with restrictions can be only project scoped")] + RestrictedTokenNotProjectScoped, + + /// Revoke Provider error. + #[error(transparent)] + RevokeProvider(#[from] RevokeProviderError), + + /// Role provider error. + #[error(transparent)] + RoleProvider { + /// The source of the error. + #[from] + source: RoleProviderError, + }, + + /// Target scope information is not found in the token. + #[error("scope information missing")] + ScopeMissing, + + /// Structures builder error. + #[error(transparent)] + StructBuilder(#[from] BuilderError), + + /// Target subject information is not found in the token. + #[error("subject information missing")] + SubjectMissing, + + /// Token restriction not found error. + #[error("token restriction {0} not found")] + TokenRestrictionNotFound(String), + + /// Revoked token error. + #[error("token has been revoked")] + TokenRevoked, + + /// Trust provider error. + #[error(transparent)] + TrustProvider(#[from] TrustProviderError), + + /// The user domain of the trustee is disabled. + #[error("trustee domain disabled")] + TrustorDomainDisabled, + + /// Unsupported token restriction driver. + #[error("driver `{0}` is not supported for the token provider")] + UnsupportedDriver(String), + + /// Unsupported token restriction driver. + #[error("driver `{0}` is not supported for the token restriction provider")] + UnsupportedTRDriver(String), + + /// The user is disabled. + #[error("user disabled")] + UserDisabled(String), + + /// The user domain is disabled. + #[error("user domain disabled")] + UserDomainDisabled, + + /// The user is not trustee. + #[error("the token subject user is not trustee of the trust")] + UserIsNotTrustee, + + /// The user cannot be found error. + #[error("user cannot be found: {0}")] + UserNotFound(String), + + /// UUID decryption error. + #[error("uuid decryption error")] + Uuid(#[from] uuid::Error), + + /// Validation error. + #[error("Token validation error: {0}")] + Validation(#[from] validator::ValidationErrors), +} diff --git a/crates/core/src/trust/types.rs b/crates/core-types/src/token/payload.rs similarity index 55% rename from crates/core/src/trust/types.rs rename to crates/core-types/src/token/payload.rs index 46456f44..03ad6835 100644 --- a/crates/core/src/trust/types.rs +++ b/crates/core-types/src/token/payload.rs @@ -11,14 +11,27 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 +//! Token provider types. -//! # Trust Extension types - -//use derive_builder::Builder; -//use serde::{Deserialize, Serialize}; - -mod provider; +mod application_credential; +mod common; +mod domain_scoped; +mod federation_domain_scoped; +mod federation_project_scoped; +mod federation_unscoped; +mod project_scoped; +mod restricted; +mod system_scoped; mod trust; +mod unscoped; -pub use provider::TrustApi; +pub use application_credential::*; +pub use domain_scoped::*; +pub use federation_domain_scoped::*; +pub use federation_project_scoped::*; +pub use federation_unscoped::*; +pub use project_scoped::*; +pub use restricted::*; +pub use system_scoped::*; pub use trust::*; +pub use unscoped::*; diff --git a/crates/core/src/token/types/application_credential.rs b/crates/core-types/src/token/payload/application_credential.rs similarity index 91% rename from crates/core/src/token/types/application_credential.rs rename to crates/core-types/src/token/payload/application_credential.rs index 530a7b7c..e87f24fb 100644 --- a/crates/core/src/token/types/application_credential.rs +++ b/crates/core-types/src/token/payload/application_credential.rs @@ -17,13 +17,13 @@ use derive_builder::Builder; use serde::Serialize; use validator::Validate; -use crate::application_credential::types::ApplicationCredential; +use super::common; +use crate::application_credential::ApplicationCredential; use crate::error::BuilderError; -use crate::identity::types::UserResponse; -use crate::resource::types::Project; -use crate::role::types::RoleRef; -use crate::token::types::Token; -use crate::token::types::common; +use crate::identity::UserResponse; +use crate::resource::Project; +use crate::role::RoleRef; +use crate::token::Token; #[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Validate)] #[builder(build_fn(error = "BuilderError"))] diff --git a/crates/core/src/token/types/common.rs b/crates/core-types/src/token/payload/common.rs similarity index 100% rename from crates/core/src/token/types/common.rs rename to crates/core-types/src/token/payload/common.rs diff --git a/crates/core/src/token/types/domain_scoped.rs b/crates/core-types/src/token/payload/domain_scoped.rs similarity index 92% rename from crates/core/src/token/types/domain_scoped.rs rename to crates/core-types/src/token/payload/domain_scoped.rs index 709dd0a2..4c39b8eb 100644 --- a/crates/core/src/token/types/domain_scoped.rs +++ b/crates/core-types/src/token/payload/domain_scoped.rs @@ -17,12 +17,12 @@ use derive_builder::Builder; use serde::Serialize; use validator::Validate; +use super::common; use crate::error::BuilderError; -use crate::identity::types::UserResponse; -use crate::resource::types::Domain; -use crate::role::types::RoleRef; -use crate::token::types::Token; -use crate::token::types::common; +use crate::identity::UserResponse; +use crate::resource::Domain; +use crate::role::RoleRef; +use crate::token::Token; #[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Validate)] #[builder(build_fn(error = "BuilderError"))] diff --git a/crates/core/src/token/types/federation_domain_scoped.rs b/crates/core-types/src/token/payload/federation_domain_scoped.rs similarity index 93% rename from crates/core/src/token/types/federation_domain_scoped.rs rename to crates/core-types/src/token/payload/federation_domain_scoped.rs index 8a7f9207..68e39bb5 100644 --- a/crates/core/src/token/types/federation_domain_scoped.rs +++ b/crates/core-types/src/token/payload/federation_domain_scoped.rs @@ -17,12 +17,12 @@ use derive_builder::Builder; use serde::Serialize; use validator::Validate; +use super::common; use crate::error::BuilderError; -use crate::identity::types::UserResponse; -use crate::resource::types::Domain; -use crate::role::types::RoleRef; -use crate::token::types::Token; -use crate::token::types::common; +use crate::identity::UserResponse; +use crate::resource::Domain; +use crate::role::RoleRef; +use crate::token::Token; /// Federated domain scope token payload. #[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Validate)] diff --git a/crates/core/src/token/types/federation_project_scoped.rs b/crates/core-types/src/token/payload/federation_project_scoped.rs similarity index 93% rename from crates/core/src/token/types/federation_project_scoped.rs rename to crates/core-types/src/token/payload/federation_project_scoped.rs index a36b75c5..4dcd8a1a 100644 --- a/crates/core/src/token/types/federation_project_scoped.rs +++ b/crates/core-types/src/token/payload/federation_project_scoped.rs @@ -17,12 +17,12 @@ use derive_builder::Builder; use serde::Serialize; use validator::Validate; +use super::common; use crate::error::BuilderError; -use crate::identity::types::UserResponse; -use crate::resource::types::Project; -use crate::role::types::RoleRef; -use crate::token::types::Token; -use crate::token::types::common; +use crate::identity::UserResponse; +use crate::resource::Project; +use crate::role::RoleRef; +use crate::token::Token; /// Federated project scope token payload. #[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Validate)] diff --git a/crates/core/src/token/types/federation_unscoped.rs b/crates/core-types/src/token/payload/federation_unscoped.rs similarity index 95% rename from crates/core/src/token/types/federation_unscoped.rs rename to crates/core-types/src/token/payload/federation_unscoped.rs index 98429f81..841fad2f 100644 --- a/crates/core/src/token/types/federation_unscoped.rs +++ b/crates/core-types/src/token/payload/federation_unscoped.rs @@ -17,10 +17,10 @@ use derive_builder::Builder; use serde::Serialize; use validator::Validate; +use super::common; use crate::error::BuilderError; -use crate::identity::types::UserResponse; -use crate::token::types::Token; -use crate::token::types::common; +use crate::identity::UserResponse; +use crate::token::Token; /// Federated unscoped token payload. #[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Validate)] diff --git a/crates/core/src/token/types/project_scoped.rs b/crates/core-types/src/token/payload/project_scoped.rs similarity index 92% rename from crates/core/src/token/types/project_scoped.rs rename to crates/core-types/src/token/payload/project_scoped.rs index a143db33..5b08a564 100644 --- a/crates/core/src/token/types/project_scoped.rs +++ b/crates/core-types/src/token/payload/project_scoped.rs @@ -17,12 +17,12 @@ use derive_builder::Builder; use serde::Serialize; use validator::Validate; +use super::common; use crate::error::BuilderError; -use crate::identity::types::UserResponse; -use crate::resource::types::Project; -use crate::role::types::RoleRef; -use crate::token::types::Token; -use crate::token::types::common; +use crate::identity::UserResponse; +use crate::resource::Project; +use crate::role::RoleRef; +use crate::token::Token; #[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Validate)] #[builder(build_fn(error = "BuilderError"))] diff --git a/crates/core-types/src/token/payload/restricted.rs b/crates/core-types/src/token/payload/restricted.rs new file mode 100644 index 00000000..3616f3d8 --- /dev/null +++ b/crates/core-types/src/token/payload/restricted.rs @@ -0,0 +1,96 @@ +// 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 +//! Restricted token types. + +use chrono::{DateTime, Utc}; +use derive_builder::Builder; +use serde::Serialize; +use validator::Validate; + +use super::common; +use crate::error::BuilderError; +use crate::identity::UserResponse; +use crate::resource::Project; +use crate::role::RoleRef; +use crate::token::Token; + +/// Restricted token payload. +#[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Validate)] +#[builder(build_fn(error = "BuilderError"))] +#[builder(setter(into))] +pub struct RestrictedPayload { + /// User ID. + #[validate(length(min = 1, max = 64))] + pub user_id: String, + + /// Authentication methods used to obtain the token. + #[builder(default, setter(name = _methods))] + #[validate(length(min = 1))] + pub methods: Vec, + /// Token audit IDs. + #[builder(default, setter(name = _audit_ids))] + #[validate(custom(function = "common::validate_audit_ids"))] + pub audit_ids: Vec, + /// Token expiration datetime in UTC. + pub expires_at: DateTime, + /// ID of the token restrictions. + #[validate(length(min = 1, max = 64))] + pub token_restriction_id: String, + /// Project ID scope for the token. + #[validate(length(min = 1, max = 64))] + pub project_id: String, + /// Whether the token can be renewed. + pub allow_renew: bool, + /// Whether the token can be rescoped. + pub allow_rescope: bool, + + #[builder(default)] + pub issued_at: DateTime, + #[builder(default)] + pub user: Option, + #[builder(default)] + pub roles: Option>, + #[builder(default)] + pub project: Option, +} + +impl RestrictedPayloadBuilder { + pub fn methods(&mut self, iter: I) -> &mut Self + where + I: Iterator, + V: Into, + { + self.methods + .get_or_insert_with(Vec::new) + .extend(iter.map(Into::into)); + self + } + + pub fn audit_ids(&mut self, iter: I) -> &mut Self + where + I: Iterator, + V: Into, + { + self.audit_ids + .get_or_insert_with(Vec::new) + .extend(iter.map(Into::into)); + self + } +} + +impl From for Token { + fn from(value: RestrictedPayload) -> Self { + Self::Restricted(value) + } +} diff --git a/crates/core/src/token/types/system_scoped.rs b/crates/core-types/src/token/payload/system_scoped.rs similarity index 94% rename from crates/core/src/token/types/system_scoped.rs rename to crates/core-types/src/token/payload/system_scoped.rs index eb60f7df..07198eca 100644 --- a/crates/core/src/token/types/system_scoped.rs +++ b/crates/core-types/src/token/payload/system_scoped.rs @@ -17,11 +17,11 @@ use derive_builder::Builder; use serde::Serialize; use validator::Validate; +use super::common; use crate::error::BuilderError; -use crate::identity::types::UserResponse; -use crate::role::types::RoleRef; -use crate::token::types::Token; -use crate::token::types::common; +use crate::identity::UserResponse; +use crate::role::RoleRef; +use crate::token::Token; #[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Validate)] #[builder(build_fn(error = "BuilderError"))] diff --git a/crates/core/src/token/types/trust.rs b/crates/core-types/src/token/payload/trust.rs similarity index 94% rename from crates/core/src/token/types/trust.rs rename to crates/core-types/src/token/payload/trust.rs index 807cc7c5..8eebfc19 100644 --- a/crates/core/src/token/types/trust.rs +++ b/crates/core-types/src/token/payload/trust.rs @@ -18,11 +18,12 @@ use derive_builder::Builder; use serde::Serialize; use validator::Validate; +use super::common; use crate::error::BuilderError; -use crate::identity::types::UserResponse; -use crate::resource::types::Project; -use crate::token::types::{Token, common}; -use crate::trust::types::Trust; +use crate::identity::UserResponse; +use crate::resource::Project; +use crate::token::Token; +use crate::trust::Trust; /// Trust token payload. #[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Validate)] diff --git a/crates/core/src/token/types/unscoped.rs b/crates/core-types/src/token/payload/unscoped.rs similarity index 95% rename from crates/core/src/token/types/unscoped.rs rename to crates/core-types/src/token/payload/unscoped.rs index 028b95dd..a405cf09 100644 --- a/crates/core/src/token/types/unscoped.rs +++ b/crates/core-types/src/token/payload/unscoped.rs @@ -17,10 +17,10 @@ use derive_builder::Builder; use serde::Serialize; use validator::Validate; +use super::common; use crate::error::BuilderError; -use crate::identity::types::UserResponse; -use crate::token::types::Token; -use crate::token::types::common; +use crate::identity::UserResponse; +use crate::token::Token; #[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Validate)] #[builder(build_fn(error = "BuilderError"))] diff --git a/crates/core/src/token/types/restricted.rs b/crates/core-types/src/token/restriction.rs similarity index 59% rename from crates/core/src/token/types/restricted.rs rename to crates/core-types/src/token/restriction.rs index 216ad4d5..9e0f990c 100644 --- a/crates/core/src/token/types/restricted.rs +++ b/crates/core-types/src/token/restriction.rs @@ -13,87 +13,11 @@ // SPDX-License-Identifier: Apache-2.0 //! Restricted token types. -use chrono::{DateTime, Utc}; use derive_builder::Builder; use serde::Serialize; -use validator::Validate; use crate::error::BuilderError; -use crate::identity::types::UserResponse; -use crate::resource::types::Project; -use crate::role::types::RoleRef; -use crate::token::types::Token; -use crate::token::types::common; - -/// Restricted token payload. -#[derive(Builder, Clone, Debug, Default, PartialEq, Serialize, Validate)] -#[builder(build_fn(error = "BuilderError"))] -#[builder(setter(into))] -pub struct RestrictedPayload { - /// User ID. - #[validate(length(min = 1, max = 64))] - pub user_id: String, - - /// Authentication methods used to obtain the token. - #[builder(default, setter(name = _methods))] - #[validate(length(min = 1))] - pub methods: Vec, - /// Token audit IDs. - #[builder(default, setter(name = _audit_ids))] - #[validate(custom(function = "common::validate_audit_ids"))] - pub audit_ids: Vec, - /// Token expiration datetime in UTC. - pub expires_at: DateTime, - /// ID of the token restrictions. - #[validate(length(min = 1, max = 64))] - pub token_restriction_id: String, - /// Project ID scope for the token. - #[validate(length(min = 1, max = 64))] - pub project_id: String, - /// Whether the token can be renewed. - pub allow_renew: bool, - /// Whether the token can be rescoped. - pub allow_rescope: bool, - - #[builder(default)] - pub issued_at: DateTime, - #[builder(default)] - pub user: Option, - #[builder(default)] - pub roles: Option>, - #[builder(default)] - pub project: Option, -} - -impl RestrictedPayloadBuilder { - pub fn methods(&mut self, iter: I) -> &mut Self - where - I: Iterator, - V: Into, - { - self.methods - .get_or_insert_with(Vec::new) - .extend(iter.map(Into::into)); - self - } - - pub fn audit_ids(&mut self, iter: I) -> &mut Self - where - I: Iterator, - V: Into, - { - self.audit_ids - .get_or_insert_with(Vec::new) - .extend(iter.map(Into::into)); - self - } -} - -impl From for Token { - fn from(value: RestrictedPayload) -> Self { - Self::Restricted(value) - } -} +use crate::role::RoleRef; /// Token restriction information. #[derive(Builder, Clone, Debug, Default, PartialEq, Serialize)] diff --git a/crates/core/src/catalog/types.rs b/crates/core-types/src/trust.rs similarity index 87% rename from crates/core/src/catalog/types.rs rename to crates/core-types/src/trust.rs index ccf69096..d2225cca 100644 --- a/crates/core/src/catalog/types.rs +++ b/crates/core-types/src/trust.rs @@ -11,9 +11,10 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 +//! # Trust provider types. -mod endpoint; -mod provider_api; -mod service; +mod error; +mod trust; -pub use provider_api::*; +pub use error::*; +pub use trust::*; diff --git a/crates/core-types/src/trust/error.rs b/crates/core-types/src/trust/error.rs new file mode 100644 index 00000000..269789dc --- /dev/null +++ b/crates/core-types/src/trust/error.rs @@ -0,0 +1,97 @@ +// 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 +//! # Trust Error +use thiserror::Error; + +use crate::auth::AuthenticationError; +use crate::error::BuilderError; +use crate::role::RoleProviderError; + +/// Trust extension error. +#[derive(Error, Debug)] +pub enum TrustProviderError { + /// Supported authentication error. + #[error(transparent)] + AuthenticationInfo { + /// The source of the error. + #[from] + source: AuthenticationError, + }, + + /// Conflict. + #[error("conflict: {0}")] + Conflict(String), + + /// Driver error. + #[error("backend driver error: {0}")] + Driver(String), + + /// Trust expiration is more than the redelegated trust can provide. + #[error("requested expiration is more than the redelegated trust can provide")] + ExpirationImpossible, + + /// DateTime parsing error. + #[error("error parsing int column as datetime: {expires_at}")] + ExpirationDateTimeParse { id: String, expires_at: i64 }, + + /// Relegated trust does not allow impersonation. + #[error( + "impersonation is not allowed because redelegated trust does not specify impersonation" + )] + RedelegatedImpersonationNotAllowed, + + /// Relegation trust must not add new roles. + #[error("some of the requested roles are not in the redelegated trust")] + RedelegatedRolesNotAvailable, + + /// Redelegation chain is longer than allowed. + #[error("redelegation depth of {length} is out of allowed range [0..{max_depth}]")] + RedelegationDeepnessExceed { length: usize, max_depth: usize }, + + /// Remaining uses of the trust is exceeded. + #[error("remaining uses exceed")] + RemainingUsesExceed, + + /// Remaining uses must be unset to redelegate a trust. + #[error("remaining uses is set while it must not be set in order to redelegate a trust")] + RemainingUsesMustBeUnset, + + /// Role provider error. + #[error(transparent)] + RoleProvider { + /// The source of the error. + #[from] + source: RoleProviderError, + }, + + /// (de)serialization error. + #[error(transparent)] + Serde { + /// The source of the error. + #[from] + source: serde_json::Error, + }, + + /// Structures builder error. + #[error(transparent)] + StructBuilder { + /// The source of the error. + #[from] + source: BuilderError, + }, + + /// Unsupported driver. + #[error("unsupported driver `{0}` for the trust provider")] + UnsupportedDriver(String), +} diff --git a/crates/core/src/trust/types/trust.rs b/crates/core-types/src/trust/trust.rs similarity index 99% rename from crates/core/src/trust/types/trust.rs rename to crates/core-types/src/trust/trust.rs index d418393a..cec689bc 100644 --- a/crates/core/src/trust/types/trust.rs +++ b/crates/core-types/src/trust/trust.rs @@ -20,7 +20,7 @@ use serde_json::Value; use validator::Validate; use crate::error::BuilderError; -use crate::role::types::RoleRef; +use crate::role::RoleRef; /// A trust object. #[derive(Builder, Clone, Debug, Default, Serialize, PartialEq, Validate)] diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index ff7956bf..21111b76 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -10,14 +10,15 @@ repository.workspace = true [dependencies] async-trait.workspace = true -axum = { workspace = true, features = ["json"], optional = true } +axum = { workspace = true, default-features = false, features = ["json"], optional = true } base64.workspace = true bcrypt = { workspace = true, features = ["alloc"] } chrono.workspace = true derive_builder.workspace = true eyre.workspace = true jsonwebtoken = { version = "10.3", features = ["rust_crypto"] } -openstack-keystone-api-types = { version = "0.1", path = "../api-types/" } +openstack-keystone-api-types = { version = "0.1", path = "../api-types/", optional = true } +openstack-keystone-core-types = { version = "0.1", path = "../core-types/" } openstack-keystone-config = { version = "0.1", path = "../config/" } mockall = { workspace = true, optional = true } rand.workspace = true @@ -33,7 +34,7 @@ tokio = { workspace = true, features = ["fs"] } tracing.workspace = true url = { workspace = true, features = ["serde"] } uuid = { workspace = true, features = ["v4"] } -validator = { workspace = true, features = ["derive"] } +validator.workspace = true [dev-dependencies] config = { workspace = true } @@ -45,6 +46,6 @@ url.workspace = true [features] default = [] -api = ["openstack-keystone-api-types/builder", "dep:axum"] +api = ["openstack-keystone-api-types/builder", "dep:axum", "openstack-keystone-api-types/conv"] bench_internals = [] mock = ["dep:mockall"] diff --git a/crates/core/README.md b/crates/core/README.md deleted file mode 100644 index 527cc844..00000000 --- a/crates/core/README.md +++ /dev/null @@ -1,112 +0,0 @@ -# OpenStack Keystone in Rust - -The legacy Keystone identity service (written in Python and maintained upstream -by OpenStack Foundation) has served the OpenStack ecosystem reliably for years. -It handles authentication, authorization, token issuance, service catalog, -project/tenant management, and federation services across thousands of -deployments. However, as we embarked on adding next-generation identity -features—such as native WebAuthn (“passkeys”), modern federation flows, direct -OIDC support, JWT login, workload authorization, restricted tokens and -service-accounts—it became clear that certain design and performance -limitations of the Python codebase would hamper efficient implementation of -these new features. - -Consequently, we initiated a project termed “Keystone-NG”: a Rust-based -component that augments rather than fully replaces the existing Keystone -service. The original plan was to implement only the new feature-set in Rust -and route those new API paths to the Rust component, while keeping the core -Python Keystone service in place for existing users and workflows. - -As development progressed, however, the breadth of new functionality (and the -opportunity to revisit some of the existing limitations) led to a partial -re-implementation of certain core identity flows in Rust. This allows us to -benefit from Rust's memory safety, concurrency model, performance, and modern -tooling, while still preserving the upstream Keystone Python service as the -canonical “master” identity service, routing only the new endpoints and -capabilities through the Rust component. - -In practice, this architecture means: - -- The upstream Python Keystone remains the main identity interface, preserving - backward compatibility, integration with other OpenStack services, existing - user workflows, catalogs, policies and plugins. - -- The Rust “Keystone-NG” component handles new functionality, specifically: - - - Native WebAuthN (passkeys) support for passwordless / phishing-resistant MFA - - - A reworked federation service, enabling modern identity brokering and - advanced federation semantics OIDC (OpenID Connect) Direct in Keystone, - enabling Keystone to act as an OIDC Provider or integrate with external - OIDC identity providers natively JWT login flows, enabling stateless, - compact tokens suitable for new micro-services, CLI, SDK, and - workload-to-workload scenarios - - - Workload Authorization, designed for service-to-service authorization in - cloud native contexts (not just human users) - - - Restricted Tokens and Service Accounts, which allow fine-grained, - limited‐scope credentials for automation, agents, and service accounts, - with explicit constraints and expiry - -By routing only the new flows through the Rust component we preserve the -stability and ecosystem compatibility of Keystone, while enabling a -forward-looking identity architecture. Over time, additional identity flows -may be migrated or refactored into the Rust component as needed, but our -current objective is to retain the existing Keystone Python implementation as -the trusted, mature baseline and incrementally build the “Keystone-NG” Rust -service as the complement. - -We believe this approach allows the best of both worlds: the trusted maturity -of Keystone's Python code-base, combined with the modern, high-safety, -high-performance capabilities of Rust where they matter most. - -## Documentation - -Project documentation can be found [here](https://openstack-experimental.github.io/keystone). -It is a work in progress. Target is to provide a comprehensive documentation of -the new functionality and provide missing insides to the python Keystone -functionality with Architecture Decision Records, Specs, Thread analysis and -many more. - -## Config - -It is supposed, that the configuration for the python Keystone can be used -without changes also for the rust implementation. - -## Api + OpenAPI - -OpenAPI are being built directly from the code to guarantee the documentation -matches the implementation. - -## Database - -Sea-ORM is being used to access database. PostgreSQL and MySQL are supported. -Functional tests [would] test the compatibility. - -## Load test - -A very brief load test is implemented in `loadtest` using `Goose` framework. -It generates test load by first incrementally increasing requests up to the -configured amount (defaults to count of the cpu cores), keeps the load for the -configured amount of time while measuring the response latency and the -throughput (RPS). - -For every PR load test suite is being executed. It is absolutely clear that the -Rust implementation currently misses certain things original Keystone doe, but -the gap is being closed over the time. However test shows difference of factor -**10-100** which is already remarkable. New tests will appear to have a more -thorough coverage of the exposed API. - -## Trying - -Trying Keystone (assuming you have the Rust build environment or you are in the -possession of the binary is as easy as `keystone -c etc/keystone.conf -vv` - -Alternatively you can try it with `docker compose -f docker-compose.yaml up`. - -## Talks - -Detailed introduction of the project was given as -* [ALASCA tech talk](https://www.youtube.com/watch?v=0Hx4Q22ZNFU) -* [OpenStack Summit 2025](https://www.youtube.com/watch?v=XOHYqE2HRw4&list=PLKqaoAnDyfgr91wN_12nwY321504Ctw1s&index=30) diff --git a/crates/core/src/api.rs b/crates/core/src/api.rs index cad5d565..f85ed1c2 100644 --- a/crates/core/src/api.rs +++ b/crates/core/src/api.rs @@ -14,12 +14,10 @@ pub mod auth; pub mod common; -pub mod error; -pub mod types; pub mod v3; pub mod v4; -pub use error::KeystoneApiError; +pub use openstack_keystone_api_types::error::KeystoneApiError; #[cfg(test)] pub(crate) mod tests { @@ -27,8 +25,8 @@ pub(crate) mod tests { use std::sync::Arc; use openstack_keystone_config::Config; + use openstack_keystone_core_types::identity::UserResponseBuilder; - use crate::identity::types::UserResponseBuilder; use crate::keystone::{Service, ServiceState}; use crate::policy::{MockPolicy, PolicyError, PolicyEvaluationResult}; use crate::provider::ProviderBuilder; diff --git a/crates/core/src/api/common.rs b/crates/core/src/api/common.rs index 99b9ca5e..af2d45bd 100644 --- a/crates/core/src/api/common.rs +++ b/crates/core/src/api/common.rs @@ -16,18 +16,37 @@ use serde::Serialize; use url::Url; use openstack_keystone_api_types::Link; +use openstack_keystone_api_types::error::KeystoneApiError; +use openstack_keystone_api_types::scope::{ProjectBuilder, ScopeProject}; use openstack_keystone_config::Config; +use openstack_keystone_core_types::resource::{Domain, Project}; +use openstack_keystone_core_types::scope::Scope as ProviderScope; -use crate::api::KeystoneApiError; -use crate::api::types::ScopeProject; use crate::auth::AuthzInfo; -use crate::common::types::Scope as ProviderScope; use crate::keystone::ServiceState; use crate::resource::{ ResourceApi, - types::{Domain, Project}, + // types::{Domain, Project}, }; +/// Get the scope [ProjectBuilder] for the given Project. +pub(super) async fn get_project_info_scope_builder( + state: &ServiceState, + project: &Project, + user_domain: &Domain, +) -> Result { + let mut project_response = ProjectBuilder::default(); + project_response.id(project.id.clone()); + project_response.name(project.name.clone()); + if project.domain_id == user_domain.id { + project_response.domain(user_domain.clone()); + } else { + let project_domain = get_domain(state, Some(&project.domain_id), None::<&str>).await?; + project_response.domain(project_domain.clone()); + } + Ok(project_response) +} + /// Get the domain by ID or Name. /// /// # Arguments @@ -225,11 +244,12 @@ mod tests { use rstest::rstest; use openstack_keystone_config::Config; + use openstack_keystone_core_types::resource::Domain; use super::*; use crate::api::tests::get_mocked_state; use crate::provider::Provider; - use crate::resource::{MockResourceProvider, types::Domain}; + use crate::resource::MockResourceProvider; #[tokio::test] async fn test_get_domain() { diff --git a/crates/core/src/api/types.rs b/crates/core/src/api/types.rs deleted file mode 100644 index b7e86e03..00000000 --- a/crates/core/src/api/types.rs +++ /dev/null @@ -1,112 +0,0 @@ -// 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 -//! Keystone API types. -pub use openstack_keystone_api_types::Link; -pub use openstack_keystone_api_types::catalog::*; -pub use openstack_keystone_api_types::scope::*; -pub use openstack_keystone_api_types::version::*; - -use crate::catalog::types::Endpoint as ProviderEndpoint; -use crate::common::types as provider_types; -use crate::resource::types as resource_provider_types; - -impl From for Endpoint { - fn from(value: ProviderEndpoint) -> Self { - Self { - id: value.id.clone(), - interface: value.interface.clone(), - url: value.url.clone(), - region: value.region_id.clone(), - region_id: value.region_id.clone(), - } - } -} - -impl From for Domain { - fn from(value: resource_provider_types::Domain) -> Self { - Self { - id: Some(value.id), - name: Some(value.name), - } - } -} - -impl From<&resource_provider_types::Domain> for Domain { - fn from(value: &resource_provider_types::Domain) -> Self { - Self { - id: Some(value.id.clone()), - name: Some(value.name.clone()), - } - } -} - -impl From for provider_types::Domain { - fn from(value: Domain) -> Self { - Self { - id: value.id, - name: value.name, - } - } -} - -impl From for Domain { - fn from(value: provider_types::Domain) -> Self { - Self { - id: value.id, - name: value.name, - } - } -} - -impl From for provider_types::Project { - fn from(value: ScopeProject) -> Self { - Self { - id: value.id, - name: value.name, - domain: value.domain.map(Into::into), - } - } -} - -impl From for ScopeProject { - fn from(value: provider_types::Project) -> Self { - Self { - id: value.id, - name: value.name, - domain: value.domain.map(Into::into), - } - } -} - -impl From<&provider_types::Project> for ScopeProject { - fn from(value: &provider_types::Project) -> Self { - Self::from(value.clone()) - } -} - -impl From for provider_types::System { - fn from(value: System) -> Self { - Self { all: value.all } - } -} - -impl From for provider_types::Scope { - fn from(value: Scope) -> Self { - match value { - Scope::Project(scope) => Self::Project(scope.into()), - Scope::Domain(scope) => Self::Domain(scope.into()), - Scope::System(scope) => Self::System(scope.into()), - } - } -} diff --git a/crates/core/src/api/v3.rs b/crates/core/src/api/v3.rs index fd263e7b..b5689745 100644 --- a/crates/core/src/api/v3.rs +++ b/crates/core/src/api/v3.rs @@ -13,8 +13,3 @@ // SPDX-License-Identifier: Apache-2.0 pub mod auth; -pub mod group; -pub mod project; -pub mod role; -pub mod role_assignment; -pub mod user; diff --git a/crates/core/src/api/v3/auth.rs b/crates/core/src/api/v3/auth.rs index 616bac87..4bb4c816 100644 --- a/crates/core/src/api/v3/auth.rs +++ b/crates/core/src/api/v3/auth.rs @@ -12,52 +12,6 @@ // // SPDX-License-Identifier: Apache-2.0 -pub use openstack_keystone_api_types::v3::auth::token::*; - -use crate::error::BuilderError; -use crate::identity::types as identity_types; -use crate::token::Token as BackendToken; - pub mod token { - mod common; pub mod token_impl; } - -impl TryFrom for identity_types::UserPasswordAuthRequest { - type Error = BuilderError; - - fn try_from(value: UserPassword) -> Result { - let mut upa = identity_types::UserPasswordAuthRequestBuilder::default(); - if let Some(id) = &value.id { - upa.id(id); - } - if let Some(name) = &value.name { - upa.name(name); - } - if let Some(domain) = &value.domain { - let mut domain_builder = identity_types::DomainBuilder::default(); - if let Some(id) = &domain.id { - domain_builder.id(id); - } - if let Some(name) = &domain.name { - domain_builder.name(name); - } - upa.domain(domain_builder.build()?); - } - upa.password(value.password.clone()); - upa.build() - } -} - -impl TryFrom<&BackendToken> for Token { - type Error = openstack_keystone_api_types::error::BuilderError; - - fn try_from(value: &BackendToken) -> Result { - let mut token = TokenBuilder::default(); - token.user(UserBuilder::default().id(value.user_id()).build()?); - token.methods(value.methods().clone()); - token.audit_ids(value.audit_ids().clone()); - token.expires_at(*value.expires_at()); - token.build() - } -} diff --git a/crates/core/src/api/v3/auth/token/common.rs b/crates/core/src/api/v3/auth/token/common.rs deleted file mode 100644 index 8dd8c611..00000000 --- a/crates/core/src/api/v3/auth/token/common.rs +++ /dev/null @@ -1,38 +0,0 @@ -// 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 - -use crate::api::common; -use crate::api::error::KeystoneApiError; -use crate::api::types::ProjectBuilder; -use crate::keystone::ServiceState; -use crate::resource::types::{Domain, Project}; - -/// Get the ProjectBuilder for the given Project. -pub(super) async fn get_project_info_builder( - state: &ServiceState, - project: &Project, - user_domain: &Domain, -) -> Result { - let mut project_response = ProjectBuilder::default(); - project_response.id(project.id.clone()); - project_response.name(project.name.clone()); - if project.domain_id == user_domain.id { - project_response.domain(user_domain.clone()); - } else { - let project_domain = - common::get_domain(state, Some(&project.domain_id), None::<&str>).await?; - project_response.domain(project_domain.clone()); - } - Ok(project_response) -} diff --git a/crates/core/src/api/v3/auth/token/token_impl.rs b/crates/core/src/api/v3/auth/token/token_impl.rs index d500afef..15198713 100644 --- a/crates/core/src/api/v3/auth/token/token_impl.rs +++ b/crates/core/src/api/v3/auth/token/token_impl.rs @@ -12,213 +12,205 @@ // // SPDX-License-Identifier: Apache-2.0 +use openstack_keystone_api_types::error::KeystoneApiError; use openstack_keystone_api_types::v3::auth::token::{System, Token, TokenBuilder, UserBuilder}; +use openstack_keystone_core_types::resource::{Domain, Project}; +use openstack_keystone_core_types::token::Token as ProviderToken; use crate::api::common; -use crate::api::error::KeystoneApiError; use crate::identity::IdentityApi; use crate::keystone::ServiceState; -use crate::resource::{ - ResourceApi, - types::{Domain, Project}, -}; -use crate::token::Token as ProviderToken; +use crate::resource::ResourceApi; use crate::trust::TrustApi; -use super::common::*; - -impl ProviderToken { - pub async fn build_api_token_v3( - &self, - state: &ServiceState, - ) -> Result { - let mut response = TokenBuilder::default(); - let mut project: Option = self.project().cloned(); - let mut domain: Option = self.domain().cloned(); - response.audit_ids(self.audit_ids().clone()); - response.methods(self.methods().clone()); - response.expires_at(*self.expires_at()); - response.issued_at(*self.issued_at()); - - let user = if let Some(user) = self.user() { - user - } else { - &state - .provider - .get_identity_provider() - .get_user(state, self.user_id()) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "user".into(), - identifier: self.user_id().clone(), - })? - }; - - let user_domain = common::get_domain(state, Some(&user.domain_id), None::<&str>).await?; - - let mut user_response: UserBuilder = UserBuilder::default(); - user_response.id(user.id.clone()); - user_response.name(user.name.clone()); - if let Some(val) = user.password_expires_at { - user_response.password_expires_at(val); - } - user_response.domain(user_domain.clone()); - response.user(user_response.build()?); - - if let Some(roles) = self.effective_roles() { - response.roles( - roles - .clone() - .into_iter() - .map(Into::into) - .collect::>(), - ); - } +pub async fn build_api_token_v3( + token: &ProviderToken, + state: &ServiceState, +) -> Result { + let mut response = TokenBuilder::default(); + let mut project: Option = token.project().cloned(); + let mut domain: Option = token.domain().cloned(); + response.audit_ids(token.audit_ids().clone()); + response.methods(token.methods().clone()); + response.expires_at(*token.expires_at()); + response.issued_at(*token.issued_at()); + + let user = if let Some(user) = token.user() { + user + } else { + &state + .provider + .get_identity_provider() + .get_user(state, token.user_id()) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "user".into(), + identifier: token.user_id().clone(), + })? + }; + + let user_domain = common::get_domain(state, Some(&user.domain_id), None::<&str>).await?; + + let mut user_response: UserBuilder = UserBuilder::default(); + user_response.id(user.id.clone()); + user_response.name(user.name.clone()); + if let Some(val) = user.password_expires_at { + user_response.password_expires_at(val); + } + user_response.domain(user_domain.clone()); + response.user(user_response.build()?); + + if let Some(roles) = token.effective_roles() { + response.roles( + roles + .clone() + .into_iter() + .map(Into::into) + .collect::>(), + ); + } - match self { - ProviderToken::ApplicationCredential(token) => { - if project.is_none() { - project = Some( - state - .provider - .get_resource_provider() - .get_project(state, &token.project_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "project".into(), - identifier: token.project_id.clone(), - })?, - ); - } + match token { + ProviderToken::ApplicationCredential(token) => { + if project.is_none() { + project = Some( + state + .provider + .get_resource_provider() + .get_project(state, &token.project_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "project".into(), + identifier: token.project_id.clone(), + })?, + ); } - ProviderToken::DomainScope(token) => { - if domain.is_none() { - domain = Some( - common::get_domain(state, Some(&token.domain_id), None::<&str>).await?, - ); - } + } + ProviderToken::DomainScope(token) => { + if domain.is_none() { + domain = + Some(common::get_domain(state, Some(&token.domain_id), None::<&str>).await?); } - ProviderToken::FederationUnscoped(_token) => {} - ProviderToken::FederationDomainScope(token) => { - if domain.is_none() { - domain = Some( - common::get_domain(state, Some(&token.domain_id), None::<&str>).await?, - ); - } + } + ProviderToken::FederationUnscoped(_token) => {} + ProviderToken::FederationDomainScope(token) => { + if domain.is_none() { + domain = + Some(common::get_domain(state, Some(&token.domain_id), None::<&str>).await?); } - ProviderToken::FederationProjectScope(token) => { - if project.is_none() { - project = Some( - state - .provider - .get_resource_provider() - .get_project(state, &token.project_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "project".into(), - identifier: token.project_id.clone(), - })?, - ); - } + } + ProviderToken::FederationProjectScope(token) => { + if project.is_none() { + project = Some( + state + .provider + .get_resource_provider() + .get_project(state, &token.project_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "project".into(), + identifier: token.project_id.clone(), + })?, + ); } - ProviderToken::ProjectScope(token) => { - if project.is_none() { - project = Some( - state - .provider - .get_resource_provider() - .get_project(state, &token.project_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "project".into(), - identifier: token.project_id.clone(), - })?, - ); - } + } + ProviderToken::ProjectScope(token) => { + if project.is_none() { + project = Some( + state + .provider + .get_resource_provider() + .get_project(state, &token.project_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "project".into(), + identifier: token.project_id.clone(), + })?, + ); } - ProviderToken::Restricted(token) => { - if project.is_none() { - project = Some( - state - .provider - .get_resource_provider() - .get_project(state, &token.project_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "project".into(), - identifier: token.project_id.clone(), - })?, - ); - } + } + ProviderToken::Restricted(token) => { + if project.is_none() { + project = Some( + state + .provider + .get_resource_provider() + .get_project(state, &token.project_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "project".into(), + identifier: token.project_id.clone(), + })?, + ); } - ProviderToken::SystemScope(_token) => { - response.system(System { all: true }); + } + ProviderToken::SystemScope(_token) => { + response.system(System { all: true }); + } + ProviderToken::Trust(token) => { + if project.is_none() { + project = Some( + state + .provider + .get_resource_provider() + .get_project(state, &token.project_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "project".into(), + identifier: token.project_id.clone(), + })?, + ); } - ProviderToken::Trust(token) => { - if project.is_none() { - project = Some( - state - .provider - .get_resource_provider() - .get_project(state, &token.project_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "project".into(), - identifier: token.project_id.clone(), - })?, - ); - } - - if let Some(trust) = &token.trust { - response.trust(trust); - } else { - response.trust( - &state - .provider - .get_trust_provider() - .get_trust(state, &token.trust_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "trust".into(), - identifier: token.trust_id.clone(), - })?, - ); - } + + if let Some(trust) = &token.trust { + response.trust(trust); + } else { + response.trust( + &state + .provider + .get_trust_provider() + .get_trust(state, &token.trust_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "trust".into(), + identifier: token.trust_id.clone(), + })?, + ); } - ProviderToken::Unscoped(_token) => {} } + ProviderToken::Unscoped(_token) => {} + } - if let Some(domain) = domain { - response.domain(domain.clone()); - } - if let Some(project) = project { - response.project( - get_project_info_builder(state, &project, &user_domain) - .await? - .build()?, - ); - } - Ok(response.build()?) + if let Some(domain) = domain { + response.domain(domain.clone()); } + if let Some(project) = project { + response.project( + common::get_project_info_scope_builder(state, &project, &user_domain) + .await? + .build()?, + ); + } + Ok(response.build()?) } #[cfg(test)] mod tests { use openstack_keystone_api_types::v3::role::RoleRef; + use openstack_keystone_core_types::identity::UserResponseBuilder; + use openstack_keystone_core_types::resource::{Domain, Project}; + use openstack_keystone_core_types::role::RoleRef as ProviderRoleRef; + use openstack_keystone_core_types::trust::Trust; + use super::*; use crate::api::tests::get_mocked_state; - use crate::identity::{MockIdentityProvider, types::UserResponseBuilder}; + use crate::identity::MockIdentityProvider; use crate::provider::Provider; - use crate::resource::{ - MockResourceProvider, - types::{Domain, Project}, - }; - use crate::role::types::RoleRef as ProviderRoleRef; + use crate::resource::MockResourceProvider; use crate::token::{ DomainScopePayload, ProjectScopePayload, Token as ProviderToken, TrustPayload, UnscopedPayload, }; - use crate::trust::types::Trust; #[tokio::test] async fn test_from_unscoped() { @@ -254,11 +246,13 @@ mod tests { let state = get_mocked_state(provider, true, None, Some(true)); - let api_token = ProviderToken::Unscoped(UnscopedPayload { - user_id: "bar".into(), - ..Default::default() - }) - .build_api_token_v3(&state) + let api_token = build_api_token_v3( + &ProviderToken::Unscoped(UnscopedPayload { + user_id: "bar".into(), + ..Default::default() + }), + &state, + ) .await .unwrap(); assert_eq!("bar", api_token.user.id); @@ -300,12 +294,14 @@ mod tests { let state = get_mocked_state(provider, true, None, None); - let api_token = ProviderToken::DomainScope(DomainScopePayload { - user_id: "bar".into(), - domain_id: "domain_id".into(), - ..Default::default() - }) - .build_api_token_v3(&state) + let api_token = build_api_token_v3( + &ProviderToken::DomainScope(DomainScopePayload { + user_id: "bar".into(), + domain_id: "domain_id".into(), + ..Default::default() + }), + &state, + ) .await .unwrap(); @@ -371,7 +367,7 @@ mod tests { ..Default::default() }); - let api_token = token.build_api_token_v3(&state).await.unwrap(); + let api_token = build_api_token_v3(&token, &state).await.unwrap(); assert_eq!("bar", api_token.user.id); assert_eq!(Some("user_domain_id"), api_token.user.domain.id.as_deref()); @@ -449,7 +445,7 @@ mod tests { ..Default::default() }); - let api_token = token.build_api_token_v3(&state).await.unwrap(); + let api_token = build_api_token_v3(&token, &state).await.unwrap(); assert_eq!("bar", api_token.user.id); assert_eq!(Some("user_domain_id"), api_token.user.domain.id.as_deref()); diff --git a/crates/core/src/api/v4.rs b/crates/core/src/api/v4.rs index f05b8525..b5689745 100644 --- a/crates/core/src/api/v4.rs +++ b/crates/core/src/api/v4.rs @@ -13,4 +13,3 @@ // SPDX-License-Identifier: Apache-2.0 pub mod auth; -pub mod token_restriction; diff --git a/crates/core/src/api/v4/auth.rs b/crates/core/src/api/v4/auth.rs index c6ce7a6a..4bb4c816 100644 --- a/crates/core/src/api/v4/auth.rs +++ b/crates/core/src/api/v4/auth.rs @@ -12,52 +12,6 @@ // // SPDX-License-Identifier: Apache-2.0 -pub use openstack_keystone_api_types::v4::auth::token::*; - -use crate::error::BuilderError; -use crate::identity::types as identity_types; -use crate::token::Token as BackendToken; - pub mod token { - pub mod common; pub mod token_impl; } - -impl TryFrom for identity_types::UserPasswordAuthRequest { - type Error = BuilderError; - - fn try_from(value: UserPassword) -> Result { - let mut upa = identity_types::UserPasswordAuthRequestBuilder::default(); - if let Some(id) = &value.id { - upa.id(id); - } - if let Some(name) = &value.name { - upa.name(name); - } - if let Some(domain) = &value.domain { - let mut domain_builder = identity_types::DomainBuilder::default(); - if let Some(id) = &domain.id { - domain_builder.id(id); - } - if let Some(name) = &domain.name { - domain_builder.name(name); - } - upa.domain(domain_builder.build()?); - } - upa.password(value.password.clone()); - upa.build() - } -} - -impl TryFrom<&BackendToken> for Token { - type Error = openstack_keystone_api_types::error::BuilderError; - - fn try_from(value: &BackendToken) -> Result { - let mut token = TokenBuilder::default(); - token.user(UserBuilder::default().id(value.user_id()).build()?); - token.methods(value.methods().clone()); - token.audit_ids(value.audit_ids().clone()); - token.expires_at(*value.expires_at()); - token.build() - } -} diff --git a/crates/core/src/api/v4/auth/token/common.rs b/crates/core/src/api/v4/auth/token/common.rs deleted file mode 100644 index 952c7aa0..00000000 --- a/crates/core/src/api/v4/auth/token/common.rs +++ /dev/null @@ -1,41 +0,0 @@ -// 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 - -use crate::api::common; -use crate::api::error::KeystoneApiError; -use crate::api::types::ProjectBuilder; -use crate::keystone::ServiceState; -use crate::resource::types::{Domain, Project}; - -/// Get the ProjectBuilder for the given Project. -pub(super) async fn get_project_info_builder( - state: &ServiceState, - project: &Project, - user_domain: &Domain, -) -> Result { - let mut project_response = ProjectBuilder::default(); - project_response.id(project.id.clone()); - project_response.name(project.name.clone()); - if project.domain_id == user_domain.id { - project_response.domain(user_domain.clone()); - } else { - let project_domain = - common::get_domain(state, Some(&project.domain_id), None::<&str>).await?; - project_response.domain(project_domain.clone()); - } - Ok(project_response) -} - -#[cfg(test)] -mod tests {} diff --git a/crates/core/src/api/v4/auth/token/token_impl.rs b/crates/core/src/api/v4/auth/token/token_impl.rs index 99d61ec2..b959e55d 100644 --- a/crates/core/src/api/v4/auth/token/token_impl.rs +++ b/crates/core/src/api/v4/auth/token/token_impl.rs @@ -12,214 +12,209 @@ // // SPDX-License-Identifier: Apache-2.0 -use openstack_keystone_api_types::v4::auth::token::{System, Token, TokenBuilder, UserBuilder}; +use openstack_keystone_api_types::error::KeystoneApiError; +use openstack_keystone_api_types::v4::auth::token::{ + System, Token as ApiToken, TokenBuilder, UserBuilder, +}; +use openstack_keystone_core_types::resource::{Domain, Project}; +use openstack_keystone_core_types::token::Token as ProviderToken; use crate::api::common; -use crate::api::error::KeystoneApiError; use crate::identity::IdentityApi; use crate::keystone::ServiceState; -use crate::resource::{ - ResourceApi, - types::{Domain, Project}, -}; -use crate::token::Token as ProviderToken; +use crate::resource::ResourceApi; use crate::trust::TrustApi; -use super::common::*; - -impl ProviderToken { - pub async fn build_api_token_v4( - &self, - state: &ServiceState, - ) -> Result { - let mut response = TokenBuilder::default(); - let mut project: Option = self.project().cloned(); - let mut domain: Option = self.domain().cloned(); - response.audit_ids(self.audit_ids().clone()); - response.methods(self.methods().clone()); - response.expires_at(*self.expires_at()); - response.issued_at(*self.issued_at()); - - let user = if let Some(user) = self.user() { - user - } else { - &state - .provider - .get_identity_provider() - .get_user(state, self.user_id()) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "user".into(), - identifier: self.user_id().clone(), - })? - }; - - let user_domain = common::get_domain(state, Some(&user.domain_id), None::<&str>).await?; - - let mut user_response: UserBuilder = UserBuilder::default(); - user_response.id(user.id.clone()); - user_response.name(user.name.clone()); - if let Some(val) = user.password_expires_at { - user_response.password_expires_at(val); - } - user_response.domain(user_domain.clone()); - response.user(user_response.build()?); - - if let Some(roles) = self.effective_roles() { - response.roles( - roles - .clone() - .into_iter() - .map(Into::into) - .collect::>(), - ); - } +pub async fn build_api_token_v4( + token: &ProviderToken, + state: &ServiceState, +) -> Result { + let mut response = TokenBuilder::default(); + let mut project: Option = token.project().cloned(); + let mut domain: Option = token.domain().cloned(); + response.audit_ids(token.audit_ids().clone()); + response.methods(token.methods().clone()); + response.expires_at(*token.expires_at()); + response.issued_at(*token.issued_at()); + + let user = if let Some(user) = token.user() { + user + } else { + &state + .provider + .get_identity_provider() + .get_user(state, token.user_id()) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "user".into(), + identifier: token.user_id().clone(), + })? + }; + + let user_domain = common::get_domain(state, Some(&user.domain_id), None::<&str>).await?; + + let mut user_response: UserBuilder = UserBuilder::default(); + user_response.id(user.id.clone()); + user_response.name(user.name.clone()); + if let Some(val) = user.password_expires_at { + user_response.password_expires_at(val); + } + user_response.domain(user_domain.clone()); + response.user(user_response.build()?); + + if let Some(roles) = token.effective_roles() { + response.roles( + roles + .clone() + .into_iter() + .map(Into::into) + .collect::>(), + ); + } - match self { - ProviderToken::ApplicationCredential(token) => { - if project.is_none() { - project = Some( - state - .provider - .get_resource_provider() - .get_project(state, &token.project_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "project".into(), - identifier: token.project_id.clone(), - })?, - ); - } + match token { + ProviderToken::ApplicationCredential(token) => { + if project.is_none() { + project = Some( + state + .provider + .get_resource_provider() + .get_project(state, &token.project_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "project".into(), + identifier: token.project_id.clone(), + })?, + ); } - ProviderToken::DomainScope(token) => { - if domain.is_none() { - domain = Some( - common::get_domain(state, Some(&token.domain_id), None::<&str>).await?, - ); - } + } + ProviderToken::DomainScope(token) => { + if domain.is_none() { + domain = + Some(common::get_domain(state, Some(&token.domain_id), None::<&str>).await?); } - ProviderToken::FederationUnscoped(_token) => {} - ProviderToken::FederationDomainScope(token) => { - if domain.is_none() { - domain = Some( - common::get_domain(state, Some(&token.domain_id), None::<&str>).await?, - ); - } + } + ProviderToken::FederationUnscoped(_token) => {} + ProviderToken::FederationDomainScope(token) => { + if domain.is_none() { + domain = + Some(common::get_domain(state, Some(&token.domain_id), None::<&str>).await?); } - ProviderToken::FederationProjectScope(token) => { - if project.is_none() { - project = Some( - state - .provider - .get_resource_provider() - .get_project(state, &token.project_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "project".into(), - identifier: token.project_id.clone(), - })?, - ); - } + } + ProviderToken::FederationProjectScope(token) => { + if project.is_none() { + project = Some( + state + .provider + .get_resource_provider() + .get_project(state, &token.project_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "project".into(), + identifier: token.project_id.clone(), + })?, + ); } - ProviderToken::ProjectScope(token) => { - if project.is_none() { - project = Some( - state - .provider - .get_resource_provider() - .get_project(state, &token.project_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "project".into(), - identifier: token.project_id.clone(), - })?, - ); - } + } + ProviderToken::ProjectScope(token) => { + if project.is_none() { + project = Some( + state + .provider + .get_resource_provider() + .get_project(state, &token.project_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "project".into(), + identifier: token.project_id.clone(), + })?, + ); } - ProviderToken::Restricted(token) => { - if project.is_none() { - project = Some( - state - .provider - .get_resource_provider() - .get_project(state, &token.project_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "project".into(), - identifier: token.project_id.clone(), - })?, - ); - } + } + ProviderToken::Restricted(token) => { + if project.is_none() { + project = Some( + state + .provider + .get_resource_provider() + .get_project(state, &token.project_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "project".into(), + identifier: token.project_id.clone(), + })?, + ); } - ProviderToken::SystemScope(_token) => { - response.system(System { all: true }); + } + ProviderToken::SystemScope(_token) => { + response.system(System { all: true }); + } + ProviderToken::Trust(token) => { + if project.is_none() { + project = Some( + state + .provider + .get_resource_provider() + .get_project(state, &token.project_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "project".into(), + identifier: token.project_id.clone(), + })?, + ); } - ProviderToken::Trust(token) => { - if project.is_none() { - project = Some( - state - .provider - .get_resource_provider() - .get_project(state, &token.project_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "project".into(), - identifier: token.project_id.clone(), - })?, - ); - } - - if let Some(trust) = &token.trust { - response.trust(trust); - } else { - response.trust( - &state - .provider - .get_trust_provider() - .get_trust(state, &token.trust_id) - .await? - .ok_or_else(|| KeystoneApiError::NotFound { - resource: "trust".into(), - identifier: token.trust_id.clone(), - })?, - ); - } + + if let Some(trust) = &token.trust { + response.trust(trust); + } else { + response.trust( + &state + .provider + .get_trust_provider() + .get_trust(state, &token.trust_id) + .await? + .ok_or_else(|| KeystoneApiError::NotFound { + resource: "trust".into(), + identifier: token.trust_id.clone(), + })?, + ); } - ProviderToken::Unscoped(_token) => {} } + ProviderToken::Unscoped(_token) => {} + } - if let Some(domain) = domain { - response.domain(domain.clone()); - } - if let Some(project) = project { - response.project( - get_project_info_builder(state, &project, &user_domain) - .await? - .build()?, - ); - } - let token = response.build()?; - Ok(token) + if let Some(domain) = domain { + response.domain(domain.clone()); } + if let Some(project) = project { + response.project( + common::get_project_info_scope_builder(state, &project, &user_domain) + .await? + .build()?, + ); + } + let token = response.build()?; + Ok(token) } #[cfg(test)] mod tests { use openstack_keystone_api_types::v3::role::RoleRef; + use openstack_keystone_core_types::identity::UserResponseBuilder; + use openstack_keystone_core_types::resource::{Domain, Project}; + use openstack_keystone_core_types::role::RoleRef as ProviderRoleRef; + use openstack_keystone_core_types::trust::Trust; use crate::api::tests::get_mocked_state; - use crate::identity::{MockIdentityProvider, types::UserResponseBuilder}; + use crate::identity::MockIdentityProvider; use crate::provider::Provider; - use crate::resource::{ - MockResourceProvider, - types::{Domain, Project}, - }; - use crate::role::types::RoleRef as ProviderRoleRef; + use crate::resource::MockResourceProvider; use crate::token::{ DomainScopePayload, ProjectScopePayload, Token as ProviderToken, TrustPayload, UnscopedPayload, }; - use crate::trust::types::Trust; + + use super::*; #[tokio::test] async fn test_from_unscoped() { @@ -254,11 +249,13 @@ mod tests { .mock_resource(resource_mock); let state = get_mocked_state(provider, true, None, None); - let api_token = ProviderToken::Unscoped(UnscopedPayload { - user_id: "bar".into(), - ..Default::default() - }) - .build_api_token_v4(&state) + let api_token = build_api_token_v4( + &ProviderToken::Unscoped(UnscopedPayload { + user_id: "bar".into(), + ..Default::default() + }), + &state, + ) .await .unwrap(); assert_eq!("bar", api_token.user.id); @@ -300,12 +297,14 @@ mod tests { let state = get_mocked_state(provider, true, None, None); - let api_token = ProviderToken::DomainScope(DomainScopePayload { - user_id: "bar".into(), - domain_id: "domain_id".into(), - ..Default::default() - }) - .build_api_token_v4(&state) + let api_token = build_api_token_v4( + &ProviderToken::DomainScope(DomainScopePayload { + user_id: "bar".into(), + domain_id: "domain_id".into(), + ..Default::default() + }), + &state, + ) .await .unwrap(); @@ -371,7 +370,7 @@ mod tests { ..Default::default() }); - let api_token = token.build_api_token_v3(&state).await.unwrap(); + let api_token = build_api_token_v4(&token, &state).await.unwrap(); assert_eq!("bar", api_token.user.id); assert_eq!(Some("user_domain_id"), api_token.user.domain.id.as_deref()); @@ -451,7 +450,7 @@ mod tests { ..Default::default() }); - let api_token = token.build_api_token_v4(&state).await.unwrap(); + let api_token = build_api_token_v4(&token, &state).await.unwrap(); assert_eq!("bar", api_token.user.id); assert_eq!(Some("user_domain_id"), api_token.user.domain.id.as_deref()); diff --git a/crates/core/src/application_credential/backend.rs b/crates/core/src/application_credential/backend.rs index a8a06d7c..4133e9b2 100644 --- a/crates/core/src/application_credential/backend.rs +++ b/crates/core/src/application_credential/backend.rs @@ -15,8 +15,9 @@ use async_trait::async_trait; +use openstack_keystone_core_types::application_credential::*; + use crate::application_credential::ApplicationCredentialProviderError; -use crate::application_credential::types::*; use crate::keystone::ServiceState; /// Application Credential backend driver interface. diff --git a/crates/core/src/application_credential/error.rs b/crates/core/src/application_credential/error.rs index 1777b6d3..fa517265 100644 --- a/crates/core/src/application_credential/error.rs +++ b/crates/core/src/application_credential/error.rs @@ -12,81 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 //! # Application credential provider error. -use thiserror::Error; - -use crate::common::password_hashing::PasswordHashError; -use crate::error::BuilderError; - -/// Application credential provider error. -#[derive(Error, Debug)] -pub enum ApplicationCredentialProviderError { - /// AccessRule with matching ID and another one matching rest of parameters - /// is found. - #[error("more than one access rule matching the ID and parameters found")] - AccessRuleConflict, - - /// Conflict. - #[error("conflict: {0}")] - Conflict(String), - - /// Driver error. - #[error("backend driver error: {0}")] - Driver(String), - - /// DateTime parsing error. - #[error("error parsing int column as datetime: {expires_at}")] - ExpirationDateTimeParse { id: String, expires_at: i64 }, - - /// Password hashing error. - #[error(transparent)] - PasswordHash { - /// The source of the error. - #[from] - source: PasswordHashError, - }, - - /// Role Database error. - #[error(transparent)] - Role { - /// The source of the error. - #[from] - source: crate::role::RoleProviderError, - }, - - /// Referred role not found. - #[error("role {0} not found")] - RoleNotFound(String), - - /// Secret is missing. - #[error("secret missing")] - SecretMissing, - - /// (de)serialization error. - #[error(transparent)] - Serde { - #[from] - source: serde_json::Error, - }, - - /// Structures builder error. - #[error(transparent)] - StructBuilder { - /// The source of the error. - #[from] - source: BuilderError, - }, - /// Unsupported driver. - #[error("unsupported driver `{0}` for the application credential provider")] - UnsupportedDriver(String), - - /// Request validation error. - #[error("request validation error: {}", source)] - Validation { - /// The source of the error. - #[from] - source: validator::ValidationErrors, - }, -} +pub use openstack_keystone_core_types::application_credential::ApplicationCredentialProviderError; impl From for ApplicationCredentialProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/application_credential/mock.rs b/crates/core/src/application_credential/mock.rs index a8763731..a6198f08 100644 --- a/crates/core/src/application_credential/mock.rs +++ b/crates/core/src/application_credential/mock.rs @@ -14,9 +14,9 @@ use async_trait::async_trait; use mockall::mock; -use crate::application_credential::ApplicationCredentialApi; -use crate::application_credential::ApplicationCredentialProviderError; -use crate::application_credential::types::*; +use openstack_keystone_core_types::application_credential::*; + +use crate::application_credential::{ApplicationCredentialApi, ApplicationCredentialProviderError}; use crate::keystone::ServiceState; mock! { diff --git a/crates/core/src/application_credential/mod.rs b/crates/core/src/application_credential/mod.rs index ac4b1324..5bc3ae52 100644 --- a/crates/core/src/application_credential/mod.rs +++ b/crates/core/src/application_credential/mod.rs @@ -113,24 +113,24 @@ //! ``` use async_trait::async_trait; +use openstack_keystone_config::Config; +use openstack_keystone_core_types::application_credential::*; + pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] mod mock; +mod provider_api; pub mod service; -pub mod types; - -use openstack_keystone_config::Config; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; use service::ApplicationCredentialService; -use types::*; pub use error::ApplicationCredentialProviderError; #[cfg(any(test, feature = "mock"))] pub use mock::MockApplicationCredentialProvider; -pub use types::ApplicationCredentialApi; +pub use provider_api::ApplicationCredentialApi; /// Application Credential Provider. pub enum ApplicationCredentialProvider { diff --git a/crates/core/src/application_credential/types/provider_api.rs b/crates/core/src/application_credential/provider_api.rs similarity index 96% rename from crates/core/src/application_credential/types/provider_api.rs rename to crates/core/src/application_credential/provider_api.rs index 912f855b..bed8dfa6 100644 --- a/crates/core/src/application_credential/types/provider_api.rs +++ b/crates/core/src/application_credential/provider_api.rs @@ -14,9 +14,9 @@ use async_trait::async_trait; -use super::application_credential::*; use crate::application_credential::error::ApplicationCredentialProviderError; use crate::keystone::ServiceState; +use openstack_keystone_core_types::application_credential::*; /// Application credentials API. #[async_trait] diff --git a/crates/core/src/application_credential/service.rs b/crates/core/src/application_credential/service.rs index 35db576b..06effbc6 100644 --- a/crates/core/src/application_credential/service.rs +++ b/crates/core/src/application_credential/service.rs @@ -23,16 +23,16 @@ use uuid::Uuid; use validator::Validate; use openstack_keystone_config::Config; +use openstack_keystone_core_types::application_credential::*; +use openstack_keystone_core_types::role::{Role, RoleListParameters}; use crate::application_credential::{ - ApplicationCredentialProviderError, backend::ApplicationCredentialBackend, types::*, + ApplicationCredentialApi, ApplicationCredentialProviderError, + backend::ApplicationCredentialBackend, }; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use crate::role::{ - RoleApi, - types::{Role, RoleListParameters}, -}; +use crate::role::RoleApi; /// Application Credential Provider. pub struct ApplicationCredentialService { diff --git a/crates/core/src/assignment/backend.rs b/crates/core/src/assignment/backend.rs index 6675eb6d..cbc9589a 100644 --- a/crates/core/src/assignment/backend.rs +++ b/crates/core/src/assignment/backend.rs @@ -14,8 +14,9 @@ use async_trait::async_trait; +use openstack_keystone_core_types::assignment::*; + use crate::assignment::AssignmentProviderError; -use crate::assignment::types::assignment::*; use crate::keystone::ServiceState; #[cfg_attr(test, mockall::automock)] diff --git a/crates/core/src/assignment/error.rs b/crates/core/src/assignment/error.rs index 45726a31..390b850c 100644 --- a/crates/core/src/assignment/error.rs +++ b/crates/core/src/assignment/error.rs @@ -12,90 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 //! # Assignment provider error types -use thiserror::Error; - -use crate::identity::error::IdentityProviderError; -use crate::resource::error::ResourceProviderError; -use crate::revoke::error::RevokeProviderError; - -/// Assignment provider error. -#[derive(Error, Debug)] -pub enum AssignmentProviderError { - /// Assignment not found. - #[error("assignment not found: {0}")] - AssignmentNotFound(String), - - /// Conflict. - #[error("conflict: {0}")] - Conflict(String), - - /// Driver error. - #[error("backend driver error: {0}")] - Driver(String), - - /// Identity provider error. - #[error(transparent)] - IdentityProvider { - #[from] - source: IdentityProviderError, - }, - - /// Invalid assignment type. - #[error("{0}")] - InvalidAssignmentType(String), - - /// Resource provider error. - #[error(transparent)] - ResourceProvider { - #[from] - source: ResourceProviderError, - }, - - /// Revoke provider error. - #[error(transparent)] - RevokeProvider { - #[from] - source: RevokeProviderError, - }, - - /// Role not found. - #[error("role {0} not found")] - RoleNotFound(String), - - /// Role provider error. - #[error(transparent)] - RoleProvider { - #[from] - source: crate::role::error::RoleProviderError, - }, - - /// (de)serialize error. - #[error(transparent)] - Serde { - #[from] - source: serde_json::Error, - }, - - /// Structures builder error. - #[error(transparent)] - StructBuilder { - /// The source of the error. - #[from] - source: crate::error::BuilderError, - }, - - /// Unsupported driver. - #[error("unsupported driver `{0}` for the assignment provider")] - UnsupportedDriver(String), - - /// Validation error. - #[error("request validation error: {}", source)] - Validation { - /// The source of the error. - #[from] - source: validator::ValidationErrors, - }, -} +pub use openstack_keystone_core_types::assignment::AssignmentProviderError; impl From for AssignmentProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/assignment/mock.rs b/crates/core/src/assignment/mock.rs index 05313ec4..ebb06819 100644 --- a/crates/core/src/assignment/mock.rs +++ b/crates/core/src/assignment/mock.rs @@ -14,9 +14,9 @@ use async_trait::async_trait; use mockall::mock; -use crate::assignment::AssignmentApi; -use crate::assignment::AssignmentProviderError; -use crate::assignment::types::*; +use openstack_keystone_core_types::assignment::*; + +use crate::assignment::{AssignmentApi, AssignmentProviderError}; use crate::keystone::ServiceState; mock! { diff --git a/crates/core/src/assignment/mod.rs b/crates/core/src/assignment/mod.rs index 7e5411f8..bd44e645 100644 --- a/crates/core/src/assignment/mod.rs +++ b/crates/core/src/assignment/mod.rs @@ -37,24 +37,24 @@ //! itself. use async_trait::async_trait; +use openstack_keystone_config::Config; +use openstack_keystone_core_types::assignment::*; + pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] mod mock; +mod provider_api; pub mod service; -pub mod types; - -use openstack_keystone_config::Config; use crate::assignment::service::AssignmentService; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use types::*; pub use error::AssignmentProviderError; #[cfg(any(test, feature = "mock"))] pub use mock::MockAssignmentProvider; -pub use types::AssignmentApi; +pub use provider_api::AssignmentApi; pub enum AssignmentProvider { Service(AssignmentService), diff --git a/crates/core/src/assignment/types/provider_api.rs b/crates/core/src/assignment/provider_api.rs similarity index 97% rename from crates/core/src/assignment/types/provider_api.rs rename to crates/core/src/assignment/provider_api.rs index 9eb07de5..9226b6ad 100644 --- a/crates/core/src/assignment/types/provider_api.rs +++ b/crates/core/src/assignment/provider_api.rs @@ -14,9 +14,9 @@ use async_trait::async_trait; -use super::assignment::*; use crate::assignment::AssignmentProviderError; use crate::keystone::ServiceState; +use openstack_keystone_core_types::assignment::*; /// The trait covering [`Role`](crate::role::types::Role) assignments between /// `actors` and `objects`. diff --git a/crates/core/src/assignment/service.rs b/crates/core/src/assignment/service.rs index 9eedf74f..575e8acb 100644 --- a/crates/core/src/assignment/service.rs +++ b/crates/core/src/assignment/service.rs @@ -16,15 +16,15 @@ use std::collections::BTreeMap; use std::sync::Arc; use openstack_keystone_config::Config; +use openstack_keystone_core_types::assignment::*; +use openstack_keystone_core_types::revoke::RevocationEventCreate; +use openstack_keystone_core_types::role::{Role, RoleListParameters}; -use crate::assignment::{AssignmentProviderError, backend::AssignmentBackend, types::*}; +use crate::assignment::{AssignmentApi, AssignmentProviderError, backend::AssignmentBackend}; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use crate::revoke::{RevokeApi, types::RevocationEventCreate}; -use crate::role::{ - RoleApi, - types::{Role, RoleListParameters}, -}; +use crate::revoke::RevokeApi; +use crate::role::RoleApi; pub struct AssignmentService { backend_driver: Arc, @@ -135,11 +135,14 @@ impl AssignmentApi for AssignmentService { #[cfg(test)] mod tests { + use openstack_keystone_core_types::revoke::*; + use openstack_keystone_core_types::role::*; + use super::*; use crate::assignment::backend::MockAssignmentBackend; use crate::provider::Provider; use crate::revoke::MockRevokeProvider; - use crate::role::{MockRoleProvider, types::*}; + use crate::role::MockRoleProvider; use crate::tests::get_mocked_state; #[tokio::test] @@ -265,7 +268,7 @@ mod tests { && params.user_id == Some("actor".into()) && params.role_id == Some("rid1".into()) }) - .returning(|_, _| Ok(crate::revoke::RevocationEvent::default())); + .returning(|_, _| Ok(RevocationEvent::default())); let state = get_mocked_state( None, Some(Provider::mocked_builder().mock_revoke(revoke_mock)), diff --git a/crates/core/src/k8s_auth/api/types.rs b/crates/core/src/auth.rs similarity index 92% rename from crates/core/src/k8s_auth/api/types.rs rename to crates/core/src/auth.rs index 562114bb..f0a9e89e 100644 --- a/crates/core/src/k8s_auth/api/types.rs +++ b/crates/core/src/auth.rs @@ -11,7 +11,4 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 - -mod auth; -mod instance; -mod role; +pub use openstack_keystone_core_types::auth::*; diff --git a/crates/core/src/catalog/backend.rs b/crates/core/src/catalog/backend.rs index 1212eec0..6528fc22 100644 --- a/crates/core/src/catalog/backend.rs +++ b/crates/core/src/catalog/backend.rs @@ -14,8 +14,9 @@ use async_trait::async_trait; +use openstack_keystone_core_types::catalog::*; + use crate::catalog::error::CatalogProviderError; -use crate::catalog::types::{Endpoint, EndpointListParameters, Service, ServiceListParameters}; use crate::keystone::ServiceState; #[cfg_attr(test, mockall::automock)] diff --git a/crates/core/src/catalog/error.rs b/crates/core/src/catalog/error.rs index 56978aea..7fe7aee8 100644 --- a/crates/core/src/catalog/error.rs +++ b/crates/core/src/catalog/error.rs @@ -11,42 +11,7 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 - -use thiserror::Error; - -use crate::error::BuilderError; - -#[derive(Error, Debug)] -pub enum CatalogProviderError { - /// Conflict. - #[error("conflict: {0}")] - Conflict(String), - - /// Driver error. - #[error("backend driver error: {0}")] - Driver(String), - - #[error("data serialization error")] - Serde { - #[from] - source: serde_json::Error, - }, - /// The service has not been found. - #[error("service {0} not found")] - ServiceNotFound(String), - - /// Structures builder error. - #[error(transparent)] - StructBuilder { - /// The source of the error. - #[from] - source: BuilderError, - }, - - /// Unsupported driver. - #[error("unsupported driver `{0}` for the catalog provider.")] - UnsupportedDriver(String), -} +pub use openstack_keystone_core_types::catalog::CatalogProviderError; impl From for CatalogProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/catalog/mock.rs b/crates/core/src/catalog/mock.rs index 80b0bfe1..6a8d175b 100644 --- a/crates/core/src/catalog/mock.rs +++ b/crates/core/src/catalog/mock.rs @@ -15,9 +15,10 @@ use async_trait::async_trait; use mockall::mock; +use openstack_keystone_core_types::catalog::*; + use crate::catalog::CatalogApi; use crate::catalog::error::CatalogProviderError; -use crate::catalog::types::{Endpoint, EndpointListParameters, Service, ServiceListParameters}; use crate::keystone::ServiceState; mock! { diff --git a/crates/core/src/catalog/mod.rs b/crates/core/src/catalog/mod.rs index da3cea70..8ded12b8 100644 --- a/crates/core/src/catalog/mod.rs +++ b/crates/core/src/catalog/mod.rs @@ -33,13 +33,14 @@ use async_trait::async_trait; use openstack_keystone_config::Config; +use openstack_keystone_core_types::catalog::*; pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] mod mock; +mod provider_api; pub mod service; -pub mod types; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; @@ -48,9 +49,7 @@ use service::CatalogService; pub use crate::catalog::error::CatalogProviderError; #[cfg(any(test, feature = "mock"))] pub use mock::MockCatalogProvider; -pub use types::CatalogApi; - -use types::*; +pub use provider_api::CatalogApi; pub enum CatalogProvider { Service(CatalogService), diff --git a/crates/core/src/catalog/types/provider_api.rs b/crates/core/src/catalog/provider_api.rs similarity index 96% rename from crates/core/src/catalog/types/provider_api.rs rename to crates/core/src/catalog/provider_api.rs index c61b5490..499a40fa 100644 --- a/crates/core/src/catalog/types/provider_api.rs +++ b/crates/core/src/catalog/provider_api.rs @@ -14,12 +14,11 @@ use async_trait::async_trait; +use openstack_keystone_core_types::catalog::*; + use crate::catalog::CatalogProviderError; use crate::keystone::ServiceState; -pub use super::endpoint::*; -pub use super::service::*; - #[async_trait] pub trait CatalogApi: Send + Sync { async fn list_services( diff --git a/crates/core/src/catalog/service.rs b/crates/core/src/catalog/service.rs index a9a5fd2d..e32c372d 100644 --- a/crates/core/src/catalog/service.rs +++ b/crates/core/src/catalog/service.rs @@ -16,8 +16,9 @@ use async_trait::async_trait; use std::sync::Arc; use openstack_keystone_config::Config; +use openstack_keystone_core_types::catalog::*; -use crate::catalog::{CatalogProviderError, backend::CatalogBackend, types::*}; +use crate::catalog::{CatalogApi, CatalogProviderError, backend::CatalogBackend}; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; diff --git a/crates/core/src/common.rs b/crates/core/src/common.rs index 95964015..20fd3c8d 100644 --- a/crates/core/src/common.rs +++ b/crates/core/src/common.rs @@ -20,7 +20,6 @@ use reqwest::Client; use tokio::sync::RwLock; pub mod password_hashing; -pub mod types; /// HTTP Client pool trait. #[async_trait] diff --git a/crates/core/src/error.rs b/crates/core/src/error.rs index 4b76ae63..20f62e87 100644 --- a/crates/core/src/error.rs +++ b/crates/core/src/error.rs @@ -16,205 +16,8 @@ //! Diverse errors that can occur during the Keystone processing (not the API). use thiserror::Error; -use crate::application_credential::error::ApplicationCredentialProviderError; -use crate::assignment::error::AssignmentProviderError; -use crate::catalog::error::CatalogProviderError; -use crate::federation::error::FederationProviderError; -use crate::identity::error::IdentityProviderError; -use crate::identity_mapping::error::IdentityMappingProviderError; -use crate::k8s_auth::error::K8sAuthProviderError; -use crate::policy::PolicyError; -use crate::resource::error::ResourceProviderError; -use crate::revoke::error::RevokeProviderError; -use crate::role::error::RoleProviderError; -use crate::token::TokenProviderError; -use crate::trust::TrustProviderError; - -/// Keystone error. -#[derive(Debug, Error)] -pub enum KeystoneError { - /// Application credential provider. - #[error(transparent)] - ApplicationCredential { - /// The source of the error. - #[from] - source: ApplicationCredentialProviderError, - }, - - /// Assignment provider. - #[error(transparent)] - AssignmentProvider { - /// The source of the error. - #[from] - source: AssignmentProviderError, - }, - - /// Catalog provider. - #[error(transparent)] - CatalogProvider { - /// The source of the error. - #[from] - source: CatalogProviderError, - }, - - /// Federation provider. - #[error(transparent)] - FederationProvider { - /// The source of the error. - #[from] - source: FederationProviderError, - }, - - /// Identity provider. - #[error(transparent)] - IdentityProvider { - /// The source of the error. - #[from] - source: IdentityProviderError, - }, - - /// Identity mapping provider. - #[error(transparent)] - IdentityMapping { - /// The source of the error. - #[from] - source: IdentityMappingProviderError, - }, - - /// IO error. - #[error(transparent)] - IO { - /// The source of the error. - #[from] - source: std::io::Error, - }, - - /// Json serialization error. - #[error("json serde error: {}", source)] - Json { - /// The source of the error. - #[from] - source: serde_json::Error, - }, - - /// K8s auth provider. - #[error(transparent)] - K8sAuthProvider { - /// The source of the error. - #[from] - source: K8sAuthProviderError, - }, - - /// Policy engine. - #[error(transparent)] - Policy { - /// The source of the error. - #[from] - source: PolicyError, - }, - - /// Policy engine is not available. - #[error("policy enforcement is requested, but not available with the enabled features")] - PolicyEnforcementNotAvailable, - - /// Resource provider. - #[error(transparent)] - ResourceProvider { - /// The source of the error. - #[from] - source: ResourceProviderError, - }, - - /// Revoke provider error. - #[error(transparent)] - RevokeProvider { - /// The source of the error. - #[from] - source: RevokeProviderError, - }, - - /// Role provider. - #[error(transparent)] - RoleProvider { - /// The source of the error. - #[from] - source: RoleProviderError, - }, - - /// Token provider. - #[error(transparent)] - TokenProvider { - /// The source of the error. - #[from] - source: TokenProviderError, - }, - - /// Trust provider. - #[error(transparent)] - TrustProvider { - /// The source of the error. - #[from] - source: TrustProviderError, - }, - - /// Url parsing error. - #[error(transparent)] - UrlParse { - #[from] - source: url::ParseError, - }, - - #[error("provider error: {}", source)] - Provider { - #[source] - source: Box, - }, - // /// WebauthN error. - // #[error(transparent)] - // Webauthn { - // /// The source of the error. - // #[from] - // source: WebauthnError, - // }, -} - -/// Builder error. -/// -/// A wrapper error that is used instead of the error generated by the -/// `derive_builder`. -#[derive(Debug, Error)] -#[non_exhaustive] -pub enum BuilderError { - /// Uninitialized field. - #[error("{0}")] - UninitializedField(String), - /// Custom validation error. - #[error("{0}")] - Validation(String), -} - -impl From for BuilderError { - fn from(s: String) -> Self { - Self::Validation(s) - } -} - -impl From for BuilderError { - fn from(value: openstack_keystone_api_types::error::BuilderError) -> Self { - match value { - openstack_keystone_api_types::error::BuilderError::UninitializedField(e) => { - Self::UninitializedField(e) - } - openstack_keystone_api_types::error::BuilderError::Validation(e) => Self::Validation(e), - } - } -} - -impl From for BuilderError { - fn from(ufe: derive_builder::UninitializedFieldError) -> Self { - Self::UninitializedField(ufe.to_string()) - } -} +pub use openstack_keystone_core_types::error::BuilderError; +pub use openstack_keystone_core_types::error::KeystoneError; /// Context aware database error. #[derive(Debug, Error)] diff --git a/crates/core/src/federation/api.rs b/crates/core/src/federation/api.rs deleted file mode 100644 index fc802455..00000000 --- a/crates/core/src/federation/api.rs +++ /dev/null @@ -1,102 +0,0 @@ -// 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 API -//! -//! - IDP -//! - Mapping -//! - Auth initialization -//! - Auth callback -// use utoipa::{ -// Modify, OpenApi, -// openapi::security::{ -// AuthorizationCode, Flow, HttpAuthScheme, HttpBuilder, OAuth2, Scopes, -// SecurityScheme, }, -// }; -// use utoipa_axum::router::OpenApiRouter; -// -// use crate::keystone::ServiceState; -// -// pub mod auth; -// mod common; -pub mod error; -// pub mod identity_provider; -// pub mod jwt; -// pub mod mapping; -// pub mod oidc; -pub mod types; -// -// /// OpenApi specification for the federation. -// #[derive(OpenApi)] -// #[openapi( -// modifiers(&SecurityFederationAddon), -// tags( -// (name="identity_providers", description=r#"Identity providers API. -// -// Identity provider resource allows to federate users from an external Identity -// Provider (i.e. Keycloak, Azure AD, etc.). -// -// Using the Identity provider requires creation of the mapping, which describes -// how to map attributes of the remote Idp to local users. -// -// Identity provider with an empty domain_id are considered globals and every -// domain may use it with appropriate mapping."#), -// (name="mappings", description=r#"Federation mappings API. -// -// Mappings define how the user attributes on the remote IDP are mapped to the -// local user. -// -// Mappings with an empty domain_id are considered globals and every domain may -// use it. Such mappings require the `domain_id_claim` attribute to be set to -// identify the domain_id for the respective user."#), -// ) -// )] -// pub struct ApiDoc; -// -// pub fn openapi_router() -> OpenApiRouter { -// OpenApiRouter::new() -// .nest("/identity_providers", identity_provider::openapi_router()) -// .nest("/mappings", mapping::openapi_router()) -// .merge(auth::openapi_router()) -// .merge(jwt::openapi_router()) -// .merge(oidc::openapi_router()) -// } -// -// struct SecurityFederationAddon; -// impl Modify for SecurityFederationAddon { -// fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) { -// if let Some(components) = openapi.components.as_mut() { -// components.add_security_scheme( -// "jwt", -// SecurityScheme::Http( -// HttpBuilder::new() -// .scheme(HttpAuthScheme::Bearer) -// .bearer_format("JWT") -// .description(Some("JWT (ID) Token issued by the -// federated IDP")) .build(), -// ), -// ); -// // TODO: This must be dynamic -// components.add_security_scheme( -// "oauth2", -// SecurityScheme::OAuth2(OAuth2::new([Flow::AuthorizationCode( -// AuthorizationCode::new( -// "https://localhost/authorization/token", -// "https://localhost/token/url", -// Scopes::from_iter([("openid", "default scope")]), -// ), -// )])), -// ); -// } -// } -// } diff --git a/crates/core/src/federation/api/error.rs b/crates/core/src/federation/api/error.rs deleted file mode 100644 index 82c95287..00000000 --- a/crates/core/src/federation/api/error.rs +++ /dev/null @@ -1,33 +0,0 @@ -// 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 - -use crate::api::error::KeystoneApiError; -use crate::federation::error::FederationProviderError; - -impl From for KeystoneApiError { - fn from(source: FederationProviderError) -> Self { - match source { - FederationProviderError::IdentityProviderNotFound(x) => Self::NotFound { - resource: "identity provider".into(), - identifier: x, - }, - FederationProviderError::MappingNotFound(x) => Self::NotFound { - resource: "mapping provider".into(), - identifier: x, - }, - FederationProviderError::Conflict(x) => Self::Conflict(x), - other => Self::InternalError(other.to_string()), - } - } -} diff --git a/crates/core/src/federation/backend.rs b/crates/core/src/federation/backend.rs index 8da4d4a4..2b824864 100644 --- a/crates/core/src/federation/backend.rs +++ b/crates/core/src/federation/backend.rs @@ -14,8 +14,9 @@ use async_trait::async_trait; +use openstack_keystone_core_types::federation::*; + use crate::federation::FederationProviderError; -use crate::federation::types::*; use crate::keystone::ServiceState; /// Backend driver interface for the Federation Provider. diff --git a/crates/core/src/federation/error.rs b/crates/core/src/federation/error.rs index 2aa9c3d8..02da35ef 100644 --- a/crates/core/src/federation/error.rs +++ b/crates/core/src/federation/error.rs @@ -12,59 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 //! # Federation provider error -use thiserror::Error; - -use crate::error::BuilderError; - -/// Federation provider error. -#[derive(Error, Debug)] -pub enum FederationProviderError { - #[error("authentication state is not found")] - AuthStateNotFound(String), - - /// Conflict. - #[error("conflict: {0}")] - Conflict(String), - - /// Driver error. - #[error("backend driver error: {0}")] - Driver(String), - - /// IDP not found. - #[error("identity provider {0} not found")] - IdentityProviderNotFound(String), - - /// Mapping not found. - #[error("mapping {0} not found")] - MappingNotFound(String), - - /// Use of token_project_id requires domain_id to be set. - #[error("`mapping.domain_id` must be set")] - MappingTokenProjectDomainUnset, - - /// Use of token_user_id requires domain_id to be set. - #[error("`mapping.domain_id` must be set")] - MappingTokenUserDomainUnset, - - /// Identity provider error. - #[error("data serialization error")] - Serde { - #[from] - source: serde_json::Error, - }, - - /// Structures builder error. - #[error(transparent)] - StructBuilder { - /// The source of the error. - #[from] - source: BuilderError, - }, - - /// Unsupported driver. - #[error("unsupported driver `{0}` for the federation provider")] - UnsupportedDriver(String), -} +pub use openstack_keystone_core_types::federation::FederationProviderError; impl From for FederationProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/federation/mock.rs b/crates/core/src/federation/mock.rs index aab8dc3e..3260a4ca 100644 --- a/crates/core/src/federation/mock.rs +++ b/crates/core/src/federation/mock.rs @@ -15,8 +15,9 @@ use async_trait::async_trait; use mockall::mock; -use crate::federation::error::FederationProviderError; -use crate::federation::types::*; +use openstack_keystone_core_types::federation::*; + +use crate::federation::{FederationApi, error::FederationProviderError}; use crate::keystone::ServiceState; mock! { diff --git a/crates/core/src/federation/mod.rs b/crates/core/src/federation/mod.rs index 4895b903..5846a91f 100644 --- a/crates/core/src/federation/mod.rs +++ b/crates/core/src/federation/mod.rs @@ -18,25 +18,23 @@ use async_trait::async_trait; use openstack_keystone_config::Config; +use openstack_keystone_core_types::federation::*; -#[cfg(feature = "api")] -pub mod api; pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] pub mod mock; +mod provider_api; pub mod service; -pub mod types; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; use service::FederationService; -use types::*; pub use crate::federation::error::FederationProviderError; #[cfg(any(test, feature = "mock"))] pub use mock::MockFederationProvider; -pub use types::FederationApi; +pub use provider_api::FederationApi; pub enum FederationProvider { Service(FederationService), diff --git a/crates/core/src/federation/types/provider.rs b/crates/core/src/federation/provider_api.rs similarity index 98% rename from crates/core/src/federation/types/provider.rs rename to crates/core/src/federation/provider_api.rs index 6c21201a..c81a6174 100644 --- a/crates/core/src/federation/types/provider.rs +++ b/crates/core/src/federation/provider_api.rs @@ -17,8 +17,9 @@ //! federation. use async_trait::async_trait; +use openstack_keystone_core_types::federation::*; + use crate::federation::error::FederationProviderError; -use crate::federation::types::*; use crate::keystone::ServiceState; /// Federation provider interface. diff --git a/crates/core/src/federation/service.rs b/crates/core/src/federation/service.rs index b23dbb5a..481c34e4 100644 --- a/crates/core/src/federation/service.rs +++ b/crates/core/src/federation/service.rs @@ -20,8 +20,9 @@ use std::sync::Arc; use uuid::Uuid; use openstack_keystone_config::Config; +use openstack_keystone_core_types::federation::*; -use crate::federation::{FederationProviderError, backend::FederationBackend, types::*}; +use crate::federation::{FederationApi, FederationProviderError, backend::FederationBackend}; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; diff --git a/crates/core/src/identity/backend.rs b/crates/core/src/identity/backend.rs index 49b2b02c..be863a23 100644 --- a/crates/core/src/identity/backend.rs +++ b/crates/core/src/identity/backend.rs @@ -16,9 +16,10 @@ use async_trait::async_trait; use chrono::{DateTime, Utc}; use std::collections::HashSet; +use openstack_keystone_core_types::identity::*; + use crate::auth::AuthenticatedInfo; use crate::identity::IdentityProviderError; -use crate::identity::types::*; use crate::keystone::ServiceState; #[cfg_attr(test, mockall::automock)] diff --git a/crates/core/src/identity/error.rs b/crates/core/src/identity/error.rs index 94bc1adf..39433c5f 100644 --- a/crates/core/src/identity/error.rs +++ b/crates/core/src/identity/error.rs @@ -11,111 +11,7 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 - -use thiserror::Error; - -use crate::common::password_hashing::PasswordHashError; -use crate::error::BuilderError; -use crate::resource::error::ResourceProviderError; - -/// Identity provider error. -#[derive(Error, Debug)] -pub enum IdentityProviderError { - /// Authentication error. - #[error(transparent)] - Authentication { - #[from] - source: crate::auth::AuthenticationError, - }, - - /// Conflict. - #[error("conflict: {0}")] - Conflict(String), - - #[error("Date calculation error")] - DateError, - - /// Driver error. - #[error("backend driver error: {0}")] - Driver(String), - - /// The group has not been found. - #[error("group {0} not found")] - GroupNotFound(String), - - #[error(transparent)] - Join { - #[from] - source: tokio::task::JoinError, - }, - - #[error("corrupted database entries for user {0}")] - MalformedUser(String), - - /// No data for local_user and passwords. - #[error("no passwords for the user {0}")] - NoPasswordsForUser(String), - - /// Row does not contain password hash. - #[error("no passwords hash on the row id: {0}")] - NoPasswordHash(String), - - /// No entry in the `user` table for the user. - #[error("no entry in the `user` table found for user_id: {0}")] - NoMainUserEntry(String), - - /// Password hashing error. - #[error("password hashing error")] - PasswordHash { - #[from] - source: PasswordHashError, - }, - - /// Resource provider error. - #[error(transparent)] - ResourceProvider { - #[from] - source: ResourceProviderError, - }, - - /// (de)serialization error. - #[error("data serialization error")] - Serde { - #[from] - source: serde_json::Error, - }, - - /// Structures builder error. - #[error(transparent)] - StructBuilder { - /// The source of the error. - #[from] - source: BuilderError, - }, - - /// Unsupported driver. - #[error("unsupported driver `{0}` for the identity provider")] - UnsupportedDriver(String), - - #[error("user id must be given")] - UserIdMissing, - - /// User ID or Name with Domain must be specified. - #[error("either user id or user name with user domain id or name must be given")] - UserIdOrNameWithDomain, - - /// The user has not been found. - #[error("user {0} not found")] - UserNotFound(String), - - /// Request validation error. - #[error("request validation error: {}", source)] - Validation { - /// The source of the error. - #[from] - source: validator::ValidationErrors, - }, -} +pub use openstack_keystone_core_types::identity::IdentityProviderError; impl From for IdentityProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/identity/mock.rs b/crates/core/src/identity/mock.rs index 8fed61fc..f41ec235 100644 --- a/crates/core/src/identity/mock.rs +++ b/crates/core/src/identity/mock.rs @@ -17,8 +17,10 @@ use chrono::{DateTime, Utc}; use mockall::mock; use std::collections::HashSet; +use openstack_keystone_core_types::identity::*; + use crate::auth::AuthenticatedInfo; -use crate::identity::{IdentityApi, error::IdentityProviderError, types::*}; +use crate::identity::{IdentityApi, error::IdentityProviderError}; use crate::keystone::ServiceState; mock! { diff --git a/crates/core/src/identity/mod.rs b/crates/core/src/identity/mod.rs index badf61e0..d4c1f199 100644 --- a/crates/core/src/identity/mod.rs +++ b/crates/core/src/identity/mod.rs @@ -34,28 +34,28 @@ //! contained in that project. use async_trait::async_trait; -use chrono::{DateTime, Utc}; +use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc}; use std::collections::HashSet; use openstack_keystone_config::Config; +use openstack_keystone_core_types::identity::*; pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] pub mod mock; -pub mod types; #[cfg(any(test, feature = "mock"))] pub use mock::MockIdentityProvider; -pub mod service; +mod provider_api; +mod service; use crate::auth::AuthenticatedInfo; -use crate::identity::types::*; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; use service::IdentityService; pub use error::IdentityProviderError; -pub use types::IdentityApi; +pub use provider_api::IdentityApi; /// Identity provider. pub enum IdentityProvider { @@ -477,3 +477,44 @@ impl IdentityApi for IdentityProvider { } } } +/// Calculate the `last_active_at` for the user entry. +pub fn get_user_last_active_at( + conf: &Config, + enabled: Option, + activity_date: NaiveDateTime, +) -> Option { + if enabled.is_some_and(|x| x) { + if conf + .security_compliance + .disable_user_account_days_inactive + .is_some() + { + Some(activity_date.date()) + } else { + None + } + } else { + None + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + #[test] + fn test_get_user_last_active_at() { + let now = Utc::now().naive_utc(); + let mut cfg = Config::default(); + assert!(get_user_last_active_at(&cfg, Some(false), now).is_none()); + assert!(get_user_last_active_at(&cfg, Some(true), now).is_none()); + assert!(get_user_last_active_at(&cfg, None, now).is_none()); + + cfg.security_compliance.disable_user_account_days_inactive = Some(1); + assert_eq!( + get_user_last_active_at(&cfg, Some(true), now), + Some(now.date()) + ); + assert!(get_user_last_active_at(&cfg, Some(false), now).is_none()); + assert!(get_user_last_active_at(&cfg, None, now).is_none()); + } +} diff --git a/crates/core/src/identity/types/provider_api.rs b/crates/core/src/identity/provider_api.rs similarity index 98% rename from crates/core/src/identity/types/provider_api.rs rename to crates/core/src/identity/provider_api.rs index 6eabaed6..e4bc9472 100644 --- a/crates/core/src/identity/types/provider_api.rs +++ b/crates/core/src/identity/provider_api.rs @@ -16,8 +16,10 @@ use async_trait::async_trait; use chrono::{DateTime, Utc}; use std::collections::HashSet; +use openstack_keystone_core_types::identity::*; + use crate::auth::AuthenticatedInfo; -use crate::identity::{IdentityProviderError, types::*}; +use crate::identity::IdentityProviderError; use crate::keystone::ServiceState; #[async_trait] diff --git a/crates/core/src/identity/service.rs b/crates/core/src/identity/service.rs index 618bde26..b157c82b 100644 --- a/crates/core/src/identity/service.rs +++ b/crates/core/src/identity/service.rs @@ -23,9 +23,10 @@ use uuid::Uuid; use validator::Validate; use openstack_keystone_config::Config; +use openstack_keystone_core_types::identity::*; use crate::auth::AuthenticatedInfo; -use crate::identity::{IdentityProviderError, backend::IdentityBackend, types::*}; +use crate::identity::{IdentityApi, IdentityProviderError, backend::IdentityBackend}; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; use crate::resource::{ResourceApi, error::ResourceProviderError}; @@ -403,9 +404,10 @@ impl IdentityApi for IdentityService { #[cfg(test)] mod tests { + use openstack_keystone_core_types::identity::{UserCreateBuilder, UserResponseBuilder}; + use super::*; use crate::identity::backend::MockIdentityBackend; - use crate::identity::types::user::{UserCreateBuilder, UserResponseBuilder}; use crate::tests::get_mocked_state; #[tokio::test] diff --git a/crates/core/src/identity_mapping/backend.rs b/crates/core/src/identity_mapping/backend.rs index e34c944c..e906b94c 100644 --- a/crates/core/src/identity_mapping/backend.rs +++ b/crates/core/src/identity_mapping/backend.rs @@ -14,7 +14,9 @@ use async_trait::async_trait; -use crate::identity_mapping::{IdentityMappingProviderError, types::*}; +use openstack_keystone_core_types::identity_mapping::*; + +use crate::identity_mapping::IdentityMappingProviderError; use crate::keystone::ServiceState; #[cfg_attr(test, mockall::automock)] diff --git a/crates/core/src/identity_mapping/error.rs b/crates/core/src/identity_mapping/error.rs index 00449182..bc8bd849 100644 --- a/crates/core/src/identity_mapping/error.rs +++ b/crates/core/src/identity_mapping/error.rs @@ -11,50 +11,7 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 - -use thiserror::Error; - -//use crate::api::error::KeystoneApiError; -use crate::error::BuilderError; - -/// Identity mapping provider error. -#[derive(Error, Debug)] -pub enum IdentityMappingProviderError { - /// Conflict. - #[error("conflict: {0}")] - Conflict(String), - - /// Driver error. - #[error("backend driver error: {0}")] - Driver(String), - - /// (de)serialization error. - #[error("data serialization error")] - Serde { - #[from] - source: serde_json::Error, - }, - - /// Structures builder error. - #[error(transparent)] - StructBuilder { - /// The source of the error. - #[from] - source: BuilderError, - }, - - /// Unsupported driver. - #[error("unsupported driver `{0}` for the identity mapping provider")] - UnsupportedDriver(String), - - /// Request validation error. - #[error("request validation error: {}", source)] - Validation { - /// The source of the error. - #[from] - source: validator::ValidationErrors, - }, -} +pub use openstack_keystone_core_types::identity_mapping::IdentityMappingProviderError; impl From for IdentityMappingProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/identity_mapping/mock.rs b/crates/core/src/identity_mapping/mock.rs index 73c11390..1eb84cf5 100644 --- a/crates/core/src/identity_mapping/mock.rs +++ b/crates/core/src/identity_mapping/mock.rs @@ -15,7 +15,9 @@ use async_trait::async_trait; use mockall::mock; -use crate::identity_mapping::{IdentityMappingApi, IdentityMappingProviderError, types::*}; +use openstack_keystone_core_types::identity_mapping::*; + +use crate::identity_mapping::{IdentityMappingApi, IdentityMappingProviderError}; use crate::keystone::ServiceState; mock! { diff --git a/crates/core/src/identity_mapping/mod.rs b/crates/core/src/identity_mapping/mod.rs index ca4ca380..98358cfc 100644 --- a/crates/core/src/identity_mapping/mod.rs +++ b/crates/core/src/identity_mapping/mod.rs @@ -20,23 +20,23 @@ use async_trait::async_trait; use openstack_keystone_config::Config; +use openstack_keystone_core_types::identity_mapping::*; pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] pub mod mock; +mod provider_api; pub mod service; -pub mod types; use crate::identity_mapping::service::IdentityMappingService; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use types::*; pub use error::IdentityMappingProviderError; #[cfg(any(test, feature = "mock"))] pub use mock::MockIdentityMappingProvider; -pub use types::IdentityMappingApi; +pub use provider_api::IdentityMappingApi; pub enum IdentityMappingProvider { Service(IdentityMappingService), diff --git a/crates/core/src/identity_mapping/types/provider_api.rs b/crates/core/src/identity_mapping/provider_api.rs similarity index 95% rename from crates/core/src/identity_mapping/types/provider_api.rs rename to crates/core/src/identity_mapping/provider_api.rs index 478285f8..8dcf060b 100644 --- a/crates/core/src/identity_mapping/types/provider_api.rs +++ b/crates/core/src/identity_mapping/provider_api.rs @@ -14,8 +14,9 @@ use async_trait::async_trait; +use openstack_keystone_core_types::identity_mapping::*; + use crate::identity_mapping::IdentityMappingProviderError; -use crate::identity_mapping::types::id_mapping::*; use crate::keystone::ServiceState; /// IdMapping provider API. diff --git a/crates/core/src/identity_mapping/service.rs b/crates/core/src/identity_mapping/service.rs index ca1d9b71..2ca16739 100644 --- a/crates/core/src/identity_mapping/service.rs +++ b/crates/core/src/identity_mapping/service.rs @@ -18,9 +18,10 @@ use async_trait::async_trait; use std::sync::Arc; use openstack_keystone_config::Config; +use openstack_keystone_core_types::identity_mapping::*; use crate::identity_mapping::{ - IdentityMappingProviderError, backend::IdentityMappingBackend, types::*, + IdentityMappingApi, IdentityMappingProviderError, backend::IdentityMappingBackend, }; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; diff --git a/crates/core/src/k8s_auth/api.rs b/crates/core/src/k8s_auth/api.rs deleted file mode 100644 index cfe81fd8..00000000 --- a/crates/core/src/k8s_auth/api.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 -pub mod error; -pub mod types; diff --git a/crates/core/src/k8s_auth/api/error.rs b/crates/core/src/k8s_auth/api/error.rs deleted file mode 100644 index e30232ba..00000000 --- a/crates/core/src/k8s_auth/api/error.rs +++ /dev/null @@ -1,59 +0,0 @@ -// 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 -use tracing::error; - -use crate::api::error::KeystoneApiError; -use crate::k8s_auth::K8sAuthProviderError; - -/// Convert `K8sAuthProviderError` error into the [HTTP](KeystoneApiError) with -/// the expected -impl From for KeystoneApiError { - fn from(source: K8sAuthProviderError) -> Self { - error!( - "Error happened during request k8s_auth processing: {:#?}", - source - ); - match source { - K8sAuthProviderError::AudienceMismatch => Self::forbidden(source), - K8sAuthProviderError::CaCertificateUnknown => Self::forbidden(source), - K8sAuthProviderError::AuthInstanceNotActive(..) => Self::forbidden(source), - K8sAuthProviderError::AuthInstanceNotFound(x) => Self::NotFound { - resource: "k8s auth configuration".into(), - identifier: x, - }, - K8sAuthProviderError::Conflict(x) => Self::Conflict(x), - K8sAuthProviderError::FailedBoundServiceAccountName(..) => Self::forbidden(source), - K8sAuthProviderError::FailedBoundServiceAccountNamespace(..) => Self::forbidden(source), - K8sAuthProviderError::Jwt { .. } => Self::forbidden(source), - K8sAuthProviderError::ExpiredToken => Self::forbidden(source), - K8sAuthProviderError::InsecureAlgorithm => Self::forbidden(source), - K8sAuthProviderError::InvalidToken => Self::forbidden(source), - K8sAuthProviderError::RoleNotFound(x) => Self::NotFound { - resource: "k8s auth role".into(), - identifier: x, - }, - K8sAuthProviderError::RoleNotActive(..) => Self::forbidden(source), - K8sAuthProviderError::RoleInstanceOwnershipMismatch(..) => Self::forbidden(source), - K8sAuthProviderError::TokenRestrictionNotFound(x) => Self::NotFound { - resource: "token restriction".into(), - identifier: x, - }, - K8sAuthProviderError::UserNotFound(x) => Self::NotFound { - resource: "user/service account".into(), - identifier: x, - }, - other => Self::InternalError(other.to_string()), - } - } -} diff --git a/crates/core/src/k8s_auth/auth.rs b/crates/core/src/k8s_auth/auth.rs index 0204ae90..fa486aa4 100644 --- a/crates/core/src/k8s_auth/auth.rs +++ b/crates/core/src/k8s_auth/auth.rs @@ -24,11 +24,16 @@ use serde_json::{Value, json}; use tokio::fs; use tracing::{debug, trace}; +use openstack_keystone_core_types::k8s_auth::*; +use openstack_keystone_core_types::token::TokenRestriction; + use crate::auth::AuthenticatedInfo; use crate::identity::IdentityApi; -use crate::k8s_auth::{K8sAuthProviderError, service::K8sAuthService, types::*}; +use crate::k8s_auth::{ + K8sAuthApi, K8sAuthProviderError, service::K8sAuthService, types::K8sClaims, +}; use crate::keystone::ServiceState; -use crate::token::{TokenApi, types::TokenRestriction}; +use crate::token::TokenApi; /// Kubernetes cluster CA certificate location. static SERVICE_ACCOUNT_CERT_PATH_STR: &str = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"; @@ -67,22 +72,26 @@ impl K8sAuthService { // Determine the CA certificate for the K8 cluster if let Some(val) = &instance.ca_cert { - client_builder = - client_builder.add_root_certificate(Certificate::from_pem(val.as_bytes())?); + client_builder = client_builder.add_root_certificate( + Certificate::from_pem(val.as_bytes()).map_err(K8sAuthProviderError::http)?, + ); } else if !instance.disable_local_ca_jwt { - client_builder = client_builder.add_root_certificate(Certificate::from_pem( - fs::read_to_string(ca_path.as_ref().unwrap_or_else(|| { - SERVICE_ACCOUNT_CERT_PATH - .get_or_init(|| PathBuf::from(SERVICE_ACCOUNT_CERT_PATH_STR)) - })) - .await - .map_err(|_| K8sAuthProviderError::CaCertificateUnknown)? - .as_bytes(), - )?); + client_builder = client_builder.add_root_certificate( + Certificate::from_pem( + fs::read_to_string(ca_path.as_ref().unwrap_or_else(|| { + SERVICE_ACCOUNT_CERT_PATH + .get_or_init(|| PathBuf::from(SERVICE_ACCOUNT_CERT_PATH_STR)) + })) + .await + .map_err(|_| K8sAuthProviderError::CaCertificateUnknown)? + .as_bytes(), + ) + .map_err(K8sAuthProviderError::http)?, + ); }; // Build the client - let shared_client = Arc::new(client_builder.build()?); + let shared_client = Arc::new(client_builder.build().map_err(K8sAuthProviderError::http)?); // Store it for future use self.http_client_pool @@ -110,7 +119,8 @@ impl K8sAuthService { role: &K8sAuthRole, ) -> Result { // Pre-flight check to fail early on expired token of wrong audience - let claims = insecure_decode::(token.expose_secret())?; + let claims = insecure_decode::(token.expose_secret()) + .map_err(K8sAuthProviderError::jwt)?; if let Some(aud) = &role.bound_audience && !claims.claims.aud.contains(aud) { @@ -138,10 +148,13 @@ impl K8sAuthService { .header("Authorization", format!("Bearer {}", token.expose_secret())) .json(&body) .send() - .await?; + .await + .map_err(K8sAuthProviderError::http)?; match response.status() { - StatusCode::OK | StatusCode::CREATED => Ok(response.json().await?), + StatusCode::OK | StatusCode::CREATED => { + Ok(response.json().await.map_err(K8sAuthProviderError::http)?) + } _ => { debug!("Kubernetes returned {:?}", response); Err(K8sAuthProviderError::InvalidToken) @@ -318,14 +331,17 @@ mod tests { use jsonwebtoken::{EncodingKey, Header, encode}; use tempfile::NamedTempFile; + use openstack_keystone_core_types::identity::*; + use openstack_keystone_core_types::token::TokenRestriction; + use super::super::backend::MockK8sAuthBackend; use super::*; use crate::common::HttpClientPool; - use crate::identity::{MockIdentityProvider, types::*}; + use crate::identity::MockIdentityProvider; use crate::keystone::Service; use crate::provider::Provider; use crate::tests::get_mocked_state; - use crate::token::{MockTokenProvider, types::TokenRestriction}; + use crate::token::MockTokenProvider; /// fake cert valid till 2036 static CA_CERT: &str = r#" diff --git a/crates/core/src/k8s_auth/backend.rs b/crates/core/src/k8s_auth/backend.rs index 508b869d..e13333f1 100644 --- a/crates/core/src/k8s_auth/backend.rs +++ b/crates/core/src/k8s_auth/backend.rs @@ -14,7 +14,9 @@ //! # K8s auth: Backends. use async_trait::async_trait; -use crate::k8s_auth::{K8sAuthProviderError, types::*}; +use openstack_keystone_core_types::k8s_auth::*; + +use crate::k8s_auth::K8sAuthProviderError; use crate::keystone::ServiceState; /// K8s auth Backend trait. diff --git a/crates/core/src/k8s_auth/error.rs b/crates/core/src/k8s_auth/error.rs index f5502312..eb7e661d 100644 --- a/crates/core/src/k8s_auth/error.rs +++ b/crates/core/src/k8s_auth/error.rs @@ -12,181 +12,31 @@ // // SPDX-License-Identifier: Apache-2.0 //! # K8s Auth error - -use thiserror::Error; - -use crate::{error::BuilderError, identity::IdentityProviderError, token::TokenProviderError}; - -/// K8s auth provider error. -#[derive(Error, Debug)] -#[non_exhaustive] -pub enum K8sAuthProviderError { - /// Role audience does not match. - #[error("role `bound_audience` does not match")] - AudienceMismatch, - - /// K8s auth instance disabled. - #[error("k8s instance {0} not active")] - AuthInstanceNotActive(String), - - /// K8s auth instance not found. - #[error("k8s instance {0} not found")] - AuthInstanceNotFound(String), - - /// K8s CA certificate is unknown. - #[error("CA certificate of the k8s cannot be identified")] - CaCertificateUnknown, - - /// Conflict. - #[error("conflict: {0}")] - Conflict(String), - - /// Driver error. - #[error("backend driver error: {source}")] - Driver { - /// The source of the error. - #[source] - source: Box, - }, - - /// Service account name of the token not matching the - /// `bound_service_account_names`. - #[error("invalid service account name of the token")] - FailedBoundServiceAccountName(String), - - /// Service account name of the token not matching the - /// `bound_service_account_namespaces`. - #[error("invalid service account namespace of the token")] - FailedBoundServiceAccountNamespace(String), - - /// JWT error. - #[error("jwt validation error: {source}")] - Jwt { - /// The source of the error. - #[from] - source: Box, - }, - - /// Expired token. - #[error("expired token")] - ExpiredToken, - - /// Http client error. - #[error(transparent)] - Http { - /// The source of the error. - #[from] - source: Box, - }, - - /// Identity provider error. - #[error(transparent)] - IdentityProvider { - /// The source of the error. - #[from] - source: Box, - }, - - /// Insecure JWT signature algorithm. - #[error("insecure jwt signature algorithm")] - InsecureAlgorithm, - - /// Invalid token. - #[error("invalid token")] - InvalidToken, - - /// Invalid token review response. - #[error("invalid token review response")] - InvalidTokenReviewResponse, - - /// K8s auth role not found. - #[error("k8s auth role {0} not found")] - RoleNotFound(String), - - /// K8s auth role not active. - #[error("k8s auth role {0} not active")] - RoleNotActive(String), - - /// Role is bound to the other configuration. - #[error("k8s auth role {0} belongs to the other instance")] - RoleInstanceOwnershipMismatch(String), - - /// Structures builder error. - #[error(transparent)] - StructBuilder { - /// The source of the error. - #[from] - source: Box, - }, - - /// Token provider error. - #[error(transparent)] - TokenProvider { - /// The source of the error. - #[from] - source: Box, - }, - - /// Token restriction not found. - #[error("token restriction {0} not found")] - TokenRestrictionNotFound(String), - - /// Token restriction MUST specify the `project_id`. - #[error("token restriction must specify `project_id`")] - TokenRestrictionMustSpecifyProjectId, - - /// Token restriction MUST specify the `user_id`. - #[error("token restriction must specify `user_id`")] - TokenRestrictionMustSpecifyUserId, - - /// Unsupported driver. - #[error("unsupported driver `{0}` for the k8s provider")] - UnsupportedDriver(String), - - /// User not found. - #[error("user {0} not found")] - UserNotFound(String), -} - -impl From for K8sAuthProviderError { - fn from(value: TokenProviderError) -> Self { - Self::TokenProvider { - source: Box::new(value), - } - } -} - -impl From for K8sAuthProviderError { - fn from(value: BuilderError) -> Self { - Self::StructBuilder { - source: Box::new(value), - } - } -} - -impl From for K8sAuthProviderError { - fn from(value: jsonwebtoken::errors::Error) -> Self { - Self::Jwt { - source: Box::new(value), - } - } -} - -impl From for K8sAuthProviderError { - fn from(value: IdentityProviderError) -> Self { - Self::IdentityProvider { - source: Box::new(value), - } - } -} - -impl From for K8sAuthProviderError { - fn from(value: reqwest::Error) -> Self { - Self::Http { - source: Box::new(value), - } - } -} +pub use openstack_keystone_core_types::k8s_auth::K8sAuthProviderError; + +//impl From for K8sAuthProviderError { +// fn from(value: jsonwebtoken::errors::Error) -> Self { +// Self::Jwt { +// source: Box::new(value), +// } +// } +//} +// +//impl From for K8sAuthProviderError { +// fn from(value: IdentityProviderError) -> Self { +// Self::IdentityProvider { +// source: Box::new(value), +// } +// } +//} +// +//impl From for K8sAuthProviderError { +// fn from(value: reqwest::Error) -> Self { +// Self::Http { +// source: Box::new(value), +// } +// } +//} impl From for K8sAuthProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/k8s_auth/mock.rs b/crates/core/src/k8s_auth/mock.rs index b8e609f8..002bf44c 100644 --- a/crates/core/src/k8s_auth/mock.rs +++ b/crates/core/src/k8s_auth/mock.rs @@ -15,10 +15,12 @@ use async_trait::async_trait; use mockall::mock; +use openstack_keystone_core_types::k8s_auth::*; +use openstack_keystone_core_types::token::TokenRestriction; + use crate::auth::AuthenticatedInfo; -use crate::k8s_auth::{K8sAuthApi, K8sAuthProviderError, types::*}; +use crate::k8s_auth::{K8sAuthApi, K8sAuthProviderError}; use crate::keystone::ServiceState; -use crate::token::types::TokenRestriction; mock! { pub K8sAuthProvider {} diff --git a/crates/core/src/k8s_auth/mod.rs b/crates/core/src/k8s_auth/mod.rs index 92ce92ed..7d2acd4a 100644 --- a/crates/core/src/k8s_auth/mod.rs +++ b/crates/core/src/k8s_auth/mod.rs @@ -15,29 +15,28 @@ use async_trait::async_trait; -#[cfg(feature = "api")] -pub mod api; mod auth; pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] mod mock; +mod provider_api; pub mod service; -pub mod types; +mod types; use openstack_keystone_config::Config; +use openstack_keystone_core_types::k8s_auth::*; +use openstack_keystone_core_types::token::TokenRestriction; use crate::auth::AuthenticatedInfo; use crate::k8s_auth::service::K8sAuthService; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use crate::token::types::TokenRestriction; -use types::*; pub use error::K8sAuthProviderError; #[cfg(any(test, feature = "mock"))] pub use mock::MockK8sAuthProvider; -pub use types::K8sAuthApi; +pub use provider_api::K8sAuthApi; /// K8s Auth provider. pub enum K8sAuthProvider { diff --git a/crates/core/src/k8s_auth/types/provider_api.rs b/crates/core/src/k8s_auth/provider_api.rs similarity index 95% rename from crates/core/src/k8s_auth/types/provider_api.rs rename to crates/core/src/k8s_auth/provider_api.rs index 861a62a5..5e301aa9 100644 --- a/crates/core/src/k8s_auth/types/provider_api.rs +++ b/crates/core/src/k8s_auth/provider_api.rs @@ -15,10 +15,12 @@ use async_trait::async_trait; +use openstack_keystone_core_types::k8s_auth::*; +use openstack_keystone_core_types::token::TokenRestriction; + use crate::auth::AuthenticatedInfo; -use crate::k8s_auth::{K8sAuthProviderError, types::*}; +use crate::k8s_auth::K8sAuthProviderError; use crate::keystone::ServiceState; -use crate::token::types::TokenRestriction; /// The trait for managing the K8s_auth functionality. #[async_trait] diff --git a/crates/core/src/k8s_auth/service.rs b/crates/core/src/k8s_auth/service.rs index 9494422a..47af1fd0 100644 --- a/crates/core/src/k8s_auth/service.rs +++ b/crates/core/src/k8s_auth/service.rs @@ -18,13 +18,14 @@ use std::sync::Arc; use async_trait::async_trait; use openstack_keystone_config::Config; +use openstack_keystone_core_types::k8s_auth::*; +use openstack_keystone_core_types::token::TokenRestriction; use crate::auth::AuthenticatedInfo; use crate::common::{HttpClientPool, HttpClientProvider}; -use crate::k8s_auth::{K8sAuthProviderError, backend::K8sAuthBackend, types::*}; +use crate::k8s_auth::{K8sAuthApi, K8sAuthProviderError, backend::K8sAuthBackend}; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use crate::token::types::TokenRestriction; /// K8s Auth provider. pub struct K8sAuthService { diff --git a/crates/core/src/k8s_auth/types.rs b/crates/core/src/k8s_auth/types.rs index acd7255e..b643d040 100644 --- a/crates/core/src/k8s_auth/types.rs +++ b/crates/core/src/k8s_auth/types.rs @@ -12,13 +12,12 @@ // // SPDX-License-Identifier: Apache-2.0 //! # K8s auth provider types definitions. +use serde::{Deserialize, Serialize}; -mod auth; -mod instance; -mod provider_api; -mod role; - -pub use auth::*; -pub use instance::*; -pub use provider_api::K8sAuthApi; -pub use role::*; +/// K8s JWT claims. +#[derive(Debug, Deserialize, Serialize)] +pub(crate) struct K8sClaims { + pub(crate) aud: Vec, + pub(crate) exp: u64, + pub(crate) sub: String, +} diff --git a/crates/core/src/policy.rs b/crates/core/src/policy.rs index 879e299b..33d895f6 100644 --- a/crates/core/src/policy.rs +++ b/crates/core/src/policy.rs @@ -63,6 +63,13 @@ pub enum PolicyError { UrlParse(#[from] url::ParseError), } +#[cfg(feature = "api")] +impl From for openstack_keystone_api_types::error::KeystoneApiError { + fn from(error: PolicyError) -> Self { + Self::forbidden(error) + } +} + #[async_trait] pub trait PolicyEnforcer: Send + Sync { async fn enforce( diff --git a/crates/core/src/resource/backend.rs b/crates/core/src/resource/backend.rs index a5707c01..7c6b552c 100644 --- a/crates/core/src/resource/backend.rs +++ b/crates/core/src/resource/backend.rs @@ -14,9 +14,10 @@ use async_trait::async_trait; +use openstack_keystone_core_types::resource::*; + use crate::keystone::ServiceState; use crate::resource::ResourceProviderError; -use crate::resource::types::*; /// Resource driver interface. #[cfg_attr(test, mockall::automock)] diff --git a/crates/core/src/resource/error.rs b/crates/core/src/resource/error.rs index 7633c586..c819efcf 100644 --- a/crates/core/src/resource/error.rs +++ b/crates/core/src/resource/error.rs @@ -11,55 +11,7 @@ // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 - -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum ResourceProviderError { - /// Conflict. - #[error("conflict: {0}")] - Conflict(String), - - /// Domain not found. - #[error("domain {0} not found")] - DomainNotFound(String), - - /// Driver error. - #[error("backend driver error: {0}")] - Driver(String), - - /// (De)Ser error. - #[error(transparent)] - Serde { - /// The source of the error. - #[from] - source: serde_json::Error, - }, - - /// Structures builder error. - #[error(transparent)] - StructBuilder { - /// The source of the error. - #[from] - source: crate::error::BuilderError, - }, - - /// Project not found. - #[error("project {0} not found")] - ProjectNotFound(String), - - /// Unsupported driver. - #[error("unsupported driver `{0}` for the resource provider")] - UnsupportedDriver(String), - - /// Request validation error. - #[error("request validation error: {}", source)] - Validation { - /// The source of the error. - #[from] - source: validator::ValidationErrors, - }, -} +pub use openstack_keystone_core_types::resource::ResourceProviderError; impl From for ResourceProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/resource/mock.rs b/crates/core/src/resource/mock.rs index 211e8860..9cc865a4 100644 --- a/crates/core/src/resource/mock.rs +++ b/crates/core/src/resource/mock.rs @@ -14,9 +14,10 @@ use async_trait::async_trait; use mockall::mock; +use openstack_keystone_core_types::resource::*; + use crate::keystone::ServiceState; -use crate::resource::error::ResourceProviderError; -use crate::resource::types::*; +use crate::resource::{ResourceApi, error::ResourceProviderError}; mock! { pub ResourceProvider {} diff --git a/crates/core/src/resource/mod.rs b/crates/core/src/resource/mod.rs index 5747fcdc..44808266 100644 --- a/crates/core/src/resource/mod.rs +++ b/crates/core/src/resource/mod.rs @@ -32,24 +32,24 @@ //! organization, or tenant. use async_trait::async_trait; +use openstack_keystone_config::Config; +use openstack_keystone_core_types::resource::*; + pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] mod mock; +mod provider_api; pub mod service; -pub mod types; - -use openstack_keystone_config::Config; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; use crate::resource::service::ResourceService; -use crate::resource::types::*; pub use crate::resource::error::ResourceProviderError; #[cfg(any(test, feature = "mock"))] pub use mock::MockResourceProvider; -pub use types::ResourceApi; +pub use provider_api::ResourceApi; pub enum ResourceProvider { Service(ResourceService), diff --git a/crates/core/src/resource/types/provider_api.rs b/crates/core/src/resource/provider_api.rs similarity index 97% rename from crates/core/src/resource/types/provider_api.rs rename to crates/core/src/resource/provider_api.rs index 40b702a2..54bd7129 100644 --- a/crates/core/src/resource/types/provider_api.rs +++ b/crates/core/src/resource/provider_api.rs @@ -14,10 +14,10 @@ use async_trait::async_trait; +use openstack_keystone_core_types::resource::*; + use crate::keystone::ServiceState; use crate::resource::ResourceProviderError; -use crate::resource::types::domain::*; -use crate::resource::types::project::*; /// Resource API. #[async_trait] diff --git a/crates/core/src/resource/service.rs b/crates/core/src/resource/service.rs index 09df7d3d..bc8a6c5d 100644 --- a/crates/core/src/resource/service.rs +++ b/crates/core/src/resource/service.rs @@ -18,10 +18,11 @@ use uuid::Uuid; use validator::Validate; use openstack_keystone_config::Config; +use openstack_keystone_core_types::resource::*; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use crate::resource::{ResourceProviderError, backend::ResourceBackend, types::*}; +use crate::resource::{ResourceApi, ResourceProviderError, backend::ResourceBackend}; pub struct ResourceService { backend_driver: Arc, diff --git a/crates/core/src/resource/types.rs b/crates/core/src/resource/types.rs deleted file mode 100644 index ae442e00..00000000 --- a/crates/core/src/resource/types.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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 domain; -mod project; -mod provider_api; - -pub use crate::resource::types::domain::*; -pub use crate::resource::types::project::*; -pub use provider_api::*; diff --git a/crates/core/src/revoke/backend.rs b/crates/core/src/revoke/backend.rs index c548a5e1..9031ea4d 100644 --- a/crates/core/src/revoke/backend.rs +++ b/crates/core/src/revoke/backend.rs @@ -15,9 +15,11 @@ //! Revocation provider Backend trait. use async_trait::async_trait; +use openstack_keystone_core_types::revoke::*; +use openstack_keystone_core_types::token::Token; + use crate::keystone::ServiceState; -use crate::revoke::{RevokeProviderError, types::*}; -use crate::token::types::Token; +use crate::revoke::RevokeProviderError; //pub mod error; diff --git a/crates/core/src/revoke/error.rs b/crates/core/src/revoke/error.rs index 34d73c81..efc05cac 100644 --- a/crates/core/src/revoke/error.rs +++ b/crates/core/src/revoke/error.rs @@ -12,28 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 //! Token revocation errors. - -use thiserror::Error; - -/// Revoke provider error. -#[derive(Error, Debug)] -pub enum RevokeProviderError { - /// Conflict. - #[error("conflict: {0}")] - Conflict(String), - - /// Driver error. - #[error("backend driver error: {0}")] - Driver(String), - - /// No audit ID in the token. - #[error("token does not have the audit_id set")] - TokenHasNoAuditId, - - /// Unsupported driver. - #[error("unsupported driver `{0}` for the revoke provider")] - UnsupportedDriver(String), -} +pub use openstack_keystone_core_types::revoke::RevokeProviderError; impl From for RevokeProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/revoke/mock.rs b/crates/core/src/revoke/mock.rs index 9cdb3f45..271436ba 100644 --- a/crates/core/src/revoke/mock.rs +++ b/crates/core/src/revoke/mock.rs @@ -15,10 +15,11 @@ use async_trait::async_trait; use mockall::mock; -use crate::revoke::{RevokeApi, RevokeProviderError, types::*}; -use crate::token::types::Token; +use openstack_keystone_core_types::revoke::*; +use openstack_keystone_core_types::token::Token; use crate::keystone::ServiceState; +use crate::revoke::{RevokeApi, RevokeProviderError}; mock! { pub RevokeProvider {} diff --git a/crates/core/src/revoke/mod.rs b/crates/core/src/revoke/mod.rs index 0700daaa..ac1888bb 100644 --- a/crates/core/src/revoke/mod.rs +++ b/crates/core/src/revoke/mod.rs @@ -41,20 +41,22 @@ pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] mod mock; +mod provider_api; pub mod service; -pub mod types; +//pub mod types; use openstack_keystone_config::Config; +use openstack_keystone_core_types::revoke::*; +use openstack_keystone_core_types::token::Token; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; use crate::revoke::service::RevokeService; -use crate::token::types::Token; pub use error::RevokeProviderError; #[cfg(any(test, feature = "mock"))] pub use mock::MockRevokeProvider; -pub use types::*; +pub use provider_api::RevokeApi; /// Revoke provider. pub enum RevokeProvider { diff --git a/crates/core/src/revoke/types/provider_api.rs b/crates/core/src/revoke/provider_api.rs similarity index 92% rename from crates/core/src/revoke/types/provider_api.rs rename to crates/core/src/revoke/provider_api.rs index 8e5754e9..e72d17fd 100644 --- a/crates/core/src/revoke/types/provider_api.rs +++ b/crates/core/src/revoke/provider_api.rs @@ -16,9 +16,11 @@ use async_trait::async_trait; +use openstack_keystone_core_types::revoke::*; +use openstack_keystone_core_types::token::Token; + use crate::keystone::ServiceState; -use crate::revoke::{RevokeProviderError, types::*}; -use crate::token::types::Token; +use crate::revoke::RevokeProviderError; /// Revocation Provider interface. #[async_trait] diff --git a/crates/core/src/revoke/service.rs b/crates/core/src/revoke/service.rs index 71146648..fd239d26 100644 --- a/crates/core/src/revoke/service.rs +++ b/crates/core/src/revoke/service.rs @@ -17,11 +17,12 @@ use async_trait::async_trait; use std::sync::Arc; use openstack_keystone_config::Config; +use openstack_keystone_core_types::revoke::*; +use openstack_keystone_core_types::token::Token; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use crate::revoke::{RevokeProviderError, backend::RevokeBackend, types::*}; -use crate::token::types::Token; +use crate::revoke::{RevokeApi, RevokeProviderError, backend::RevokeBackend}; /// Revoke provider. pub struct RevokeService { diff --git a/crates/core/src/revoke/types.rs b/crates/core/src/revoke/types.rs deleted file mode 100644 index 597920f2..00000000 --- a/crates/core/src/revoke/types.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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 -//! Token revocation types definitions. -//! Revocation provider types. - -mod provider_api; -mod revocation_event; - -pub use provider_api::RevokeApi; -pub use revocation_event::*; diff --git a/crates/core/src/role/backend.rs b/crates/core/src/role/backend.rs index e078e7f7..8bfc28be 100644 --- a/crates/core/src/role/backend.rs +++ b/crates/core/src/role/backend.rs @@ -15,8 +15,10 @@ use async_trait::async_trait; use std::collections::{BTreeMap, BTreeSet}; +use openstack_keystone_core_types::role::*; + use crate::keystone::ServiceState; -use crate::role::{RoleProviderError, types::role::*}; +use crate::role::RoleProviderError; #[cfg_attr(test, mockall::automock)] #[async_trait] diff --git a/crates/core/src/role/error.rs b/crates/core/src/role/error.rs index f7058e01..9ef00bd5 100644 --- a/crates/core/src/role/error.rs +++ b/crates/core/src/role/error.rs @@ -12,50 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 //! # Role provider error types -use thiserror::Error; - -/// Role provider error. -#[derive(Error, Debug)] -pub enum RoleProviderError { - /// Conflict. - #[error("conflict: {0}")] - Conflict(String), - - /// Driver error. - #[error("backend driver error: {0}")] - Driver(String), - - /// Role not found. - #[error("role {0} not found")] - RoleNotFound(String), - - /// (de)serialize error. - #[error(transparent)] - Serde { - #[from] - source: serde_json::Error, - }, - - /// Structures builder error. - #[error(transparent)] - StructBuilder { - /// The source of the error. - #[from] - source: crate::error::BuilderError, - }, - - /// Unsupported driver. - #[error("unsupported driver `{0}` for the role provider")] - UnsupportedDriver(String), - - /// Validation error. - #[error("request validation error: {}", source)] - Validation { - /// The source of the error. - #[from] - source: validator::ValidationErrors, - }, -} +pub use openstack_keystone_core_types::role::RoleProviderError; impl From for RoleProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/role/mock.rs b/crates/core/src/role/mock.rs index 883b7680..61d290e3 100644 --- a/crates/core/src/role/mock.rs +++ b/crates/core/src/role/mock.rs @@ -15,8 +15,10 @@ use async_trait::async_trait; use mockall::mock; use std::collections::{BTreeMap, BTreeSet}; +use openstack_keystone_core_types::role::*; + use crate::keystone::ServiceState; -use crate::role::{RoleApi, RoleProviderError, types::*}; +use crate::role::{RoleApi, RoleProviderError}; mock! { pub RoleProvider {} diff --git a/crates/core/src/role/mod.rs b/crates/core/src/role/mod.rs index a9dcb796..d54199cd 100644 --- a/crates/core/src/role/mod.rs +++ b/crates/core/src/role/mod.rs @@ -34,23 +34,24 @@ use async_trait::async_trait; use std::collections::{BTreeMap, BTreeSet}; +use openstack_keystone_config::Config; +use openstack_keystone_core_types::role::*; + pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] mod mock; +mod provider_api; pub mod service; -pub mod types; - -use openstack_keystone_config::Config; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use crate::role::{service::RoleService, types::*}; +use crate::role::service::RoleService; pub use error::RoleProviderError; #[cfg(any(test, feature = "mock"))] pub use mock::MockRoleProvider; -pub use types::RoleApi; +pub use provider_api::RoleApi; pub enum RoleProvider { Service(RoleService), diff --git a/crates/core/src/role/types/provider_api.rs b/crates/core/src/role/provider_api.rs similarity index 97% rename from crates/core/src/role/types/provider_api.rs rename to crates/core/src/role/provider_api.rs index 82c6d7c7..ab2d9c17 100644 --- a/crates/core/src/role/types/provider_api.rs +++ b/crates/core/src/role/provider_api.rs @@ -15,7 +15,8 @@ use async_trait::async_trait; use std::collections::{BTreeMap, BTreeSet}; -use super::role::*; +use openstack_keystone_core_types::role::*; + use crate::keystone::ServiceState; use crate::role::RoleProviderError; diff --git a/crates/core/src/role/service.rs b/crates/core/src/role/service.rs index 2ba82a24..a88ed485 100644 --- a/crates/core/src/role/service.rs +++ b/crates/core/src/role/service.rs @@ -19,10 +19,11 @@ use uuid::Uuid; use validator::Validate; use openstack_keystone_config::Config; +use openstack_keystone_core_types::role::*; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use crate::role::{RoleProviderError, backend::RoleBackend, types::*}; +use crate::role::{RoleApi, RoleProviderError, backend::RoleBackend}; pub struct RoleService { backend_driver: Arc, diff --git a/crates/core/src/role/types.rs b/crates/core/src/role/types.rs index be295e31..62da7059 100644 --- a/crates/core/src/role/types.rs +++ b/crates/core/src/role/types.rs @@ -13,7 +13,7 @@ // SPDX-License-Identifier: Apache-2.0 pub mod provider_api; -pub mod role; +//pub mod role; pub use provider_api::*; -pub use role::*; +pub use openstack_keystone_core_types::role::*; diff --git a/crates/core/src/token/backend.rs b/crates/core/src/token/backend.rs index 64487339..a7cff395 100644 --- a/crates/core/src/token/backend.rs +++ b/crates/core/src/token/backend.rs @@ -15,9 +15,10 @@ use openstack_keystone_config::Config; -use crate::token::{TokenProviderError, types::*}; +use openstack_keystone_core_types::token::*; use crate::keystone::ServiceState; +use crate::token::TokenProviderError; /// Token Provider backend interface. #[cfg_attr(test, mockall::automock)] diff --git a/crates/core/src/token/error.rs b/crates/core/src/token/error.rs index 858b26f1..1c09a694 100644 --- a/crates/core/src/token/error.rs +++ b/crates/core/src/token/error.rs @@ -12,166 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 //! Token provider errors. - -use thiserror::Error; - -use crate::error::BuilderError; - -/// Token provider error. -#[derive(Error, Debug)] -#[non_exhaustive] -pub enum TokenProviderError { - /// Actor has no roles on the target scope. - #[error("actor has no roles on scope")] - ActorHasNoRolesOnTarget, - - /// Application Credential has expired. - #[error("application credential has expired")] - ApplicationCredentialExpired, - - /// Application Credential used in the token is not found. - #[error("application credential with id: {0} not found")] - ApplicationCredentialNotFound(String), - - /// Application credential provider error. - #[error(transparent)] - ApplicationCredentialProvider { - /// The source of the error. - #[from] - source: crate::application_credential::error::ApplicationCredentialProviderError, - }, - - /// Application Credential is bound to the other project. - #[error("application credential is bound to another project")] - ApplicationCredentialScopeMismatch, - - /// Assignment provider error. - #[error(transparent)] - AssignmentProvider { - /// The source of the error. - #[from] - source: crate::assignment::error::AssignmentProviderError, - }, - - /// Authentication error. - #[error(transparent)] - Authentication(#[from] crate::auth::AuthenticationError), - - /// Conflict. - #[error("{message}")] - Conflict { message: String, context: String }, - - /// The domain is disabled. - #[error("domain is disabled")] - DomainDisabled(String), - - /// Driver error. - #[error("backend driver error: {source}")] - Driver { - #[source] - source: Box, - }, - - /// Expired token. - #[error("token expired")] - Expired, - - /// Expiry calculation error. - #[error("token expiry calculation failed")] - ExpiryCalculation, - - /// Federated payload missing data error. - #[error("federated payload must contain idp_id and protocol_id")] - FederatedPayloadMissingData, - - /// Identity provider error. - #[error(transparent)] - IdentityProvider(#[from] crate::identity::error::IdentityProviderError), - - /// The project is disabled. - #[error("project disabled")] - ProjectDisabled(String), - - /// Resource provider error. - #[error(transparent)] - ResourceProvider(#[from] crate::resource::error::ResourceProviderError), - - /// Restricted token project scoped error. - #[error("token with restrictions can be only project scoped")] - RestrictedTokenNotProjectScoped, - - /// Revoke Provider error. - #[error(transparent)] - RevokeProvider(#[from] crate::revoke::error::RevokeProviderError), - - /// Role provider error. - #[error(transparent)] - RoleProvider { - /// The source of the error. - #[from] - source: crate::role::error::RoleProviderError, - }, - - /// Target scope information is not found in the token. - #[error("scope information missing")] - ScopeMissing, - - /// Structures builder error. - #[error(transparent)] - StructBuilder(#[from] BuilderError), - - /// Target subject information is not found in the token. - #[error("subject information missing")] - SubjectMissing, - - /// Token restriction not found error. - #[error("token restriction {0} not found")] - TokenRestrictionNotFound(String), - - /// Revoked token error. - #[error("token has been revoked")] - TokenRevoked, - - /// Trust provider error. - #[error(transparent)] - TrustProvider(#[from] crate::trust::TrustProviderError), - - /// The user domain of the trustee is disabled. - #[error("trustee domain disabled")] - TrustorDomainDisabled, - - /// Unsupported token restriction driver. - #[error("driver `{0}` is not supported for the token provider")] - UnsupportedDriver(String), - - /// Unsupported token restriction driver. - #[error("driver `{0}` is not supported for the token restriction provider")] - UnsupportedTRDriver(String), - - /// The user is disabled. - #[error("user disabled")] - UserDisabled(String), - - /// The user domain is disabled. - #[error("user domain disabled")] - UserDomainDisabled, - - /// The user is not trustee. - #[error("the token subject user is not trustee of the trust")] - UserIsNotTrustee, - - /// The user cannot be found error. - #[error("user cannot be found: {0}")] - UserNotFound(String), - - /// UUID decryption error. - #[error("uuid decryption error")] - Uuid(#[from] uuid::Error), - - /// Validation error. - #[error("Token validation error: {0}")] - Validation(#[from] validator::ValidationErrors), -} +pub use openstack_keystone_core_types::token::TokenProviderError; impl From for TokenProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/token/mock.rs b/crates/core/src/token/mock.rs index 87c90a8b..424a6ac3 100644 --- a/crates/core/src/token/mock.rs +++ b/crates/core/src/token/mock.rs @@ -16,14 +16,13 @@ use async_trait::async_trait; use mockall::mock; +use openstack_keystone_core_types::token::*; + use super::error::TokenProviderError; use crate::auth::{AuthenticatedInfo, AuthzInfo}; use crate::keystone::ServiceState; -use super::{ - Token, TokenApi, TokenRestriction, TokenRestrictionCreate, TokenRestrictionListParameters, - TokenRestrictionUpdate, -}; +use super::TokenApi; mock! { pub TokenProvider {} diff --git a/crates/core/src/token/mod.rs b/crates/core/src/token/mod.rs index 983d4eb4..79b00cdc 100644 --- a/crates/core/src/token/mod.rs +++ b/crates/core/src/token/mod.rs @@ -22,21 +22,23 @@ use async_trait::async_trait; use openstack_keystone_config::Config; +pub use openstack_keystone_core_types::token::*; pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] mod mock; +mod provider_api; pub mod service; -pub mod types; +mod validate; use crate::auth::{AuthenticatedInfo, AuthzInfo}; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; use crate::token::service::TokenService; pub use error::TokenProviderError; +pub use provider_api::TokenApi; -pub use crate::token::types::*; #[cfg(any(test, feature = "mock"))] pub use mock::MockTokenProvider; diff --git a/crates/core/src/token/types/provider_api.rs b/crates/core/src/token/provider_api.rs similarity index 98% rename from crates/core/src/token/types/provider_api.rs rename to crates/core/src/token/provider_api.rs index 99f6f2da..30f1cdce 100644 --- a/crates/core/src/token/types/provider_api.rs +++ b/crates/core/src/token/provider_api.rs @@ -15,12 +15,12 @@ use async_trait::async_trait; +use openstack_keystone_core_types::token::*; + use crate::auth::{AuthenticatedInfo, AuthzInfo}; use crate::keystone::ServiceState; use crate::token::TokenProviderError; -use super::*; - /// Token Provider interface. #[async_trait] pub trait TokenApi: Send + Sync { diff --git a/crates/core/src/token/service.rs b/crates/core/src/token/service.rs index ac248100..84fd63b3 100644 --- a/crates/core/src/token/service.rs +++ b/crates/core/src/token/service.rs @@ -28,33 +28,33 @@ use tracing::{debug, trace}; use uuid::Uuid; use openstack_keystone_config::Config; +use openstack_keystone_core_types::assignment::{ + RoleAssignmentListParameters, RoleAssignmentListParametersBuilder, +}; +use openstack_keystone_core_types::resource::{Domain, Project}; +use openstack_keystone_core_types::role::RoleRef; +use openstack_keystone_core_types::token::payload::*; +use openstack_keystone_core_types::token::*; +use openstack_keystone_core_types::trust::*; use crate::auth::{AuthenticatedInfo, AuthenticationError, AuthzInfo}; use crate::identity::IdentityApi; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use crate::resource::{ - ResourceApi, - types::{Domain, Project}, -}; +use crate::resource::ResourceApi; use crate::revoke::RevokeApi; +use crate::token::validate::{validate_token_scope, validate_token_subject}; use crate::token::{ - TokenProviderError, + TokenApi, TokenProviderError, backend::{TokenBackend, TokenRestrictionBackend}, }; use crate::{ application_credential::ApplicationCredentialApi, - assignment::{ - AssignmentApi, - error::AssignmentProviderError, - types::{RoleAssignmentListParameters, RoleAssignmentListParametersBuilder}, - }, - role::{RoleApi, types::RoleRef}, - trust::{TrustApi, types::Trust}, + assignment::{AssignmentApi, error::AssignmentProviderError}, + role::RoleApi, + trust::TrustApi, }; -pub use crate::token::types::*; - pub struct TokenService { config: Config, backend_driver: Arc, @@ -843,8 +843,8 @@ impl TokenApi for TokenService { return Err(TokenProviderError::TokenRevoked); } - token.validate_subject(state).await?; - token.validate_scope(state).await?; + validate_token_subject(&token, state).await?; + validate_token_scope(&token, state).await?; Ok(token) } @@ -1010,24 +1010,23 @@ mod tests { use uuid::Uuid; use openstack_keystone_config::Config; + use openstack_keystone_core_types::application_credential::*; + use openstack_keystone_core_types::assignment::*; + use openstack_keystone_core_types::identity::UserResponseBuilder; + use openstack_keystone_core_types::resource::*; + use openstack_keystone_core_types::trust::*; use super::super::tests::setup_config; use super::*; - use crate::application_credential::{ - MockApplicationCredentialProvider, types::ApplicationCredential, - }; - use crate::assignment::{ - MockAssignmentProvider, - types::{Assignment, AssignmentType, RoleAssignmentListParameters}, - }; + use crate::application_credential::MockApplicationCredentialProvider; + use crate::assignment::MockAssignmentProvider; use crate::auth::AuthenticatedInfoBuilder; - use crate::identity::{MockIdentityProvider, types::UserResponseBuilder}; + use crate::identity::MockIdentityProvider; use crate::provider::Provider; - use crate::resource::{MockResourceProvider, types::*}; + use crate::resource::MockResourceProvider; use crate::revoke::MockRevokeProvider; use crate::tests::get_mocked_state; use crate::token::backend::{MockTokenBackend, MockTokenRestrictionBackend}; - use crate::trust::types::*; /// Generate test token to use for validation testing. fn generate_token(validity: Option) -> Result { diff --git a/crates/core/src/token/validate.rs b/crates/core/src/token/validate.rs new file mode 100644 index 00000000..b74835a1 --- /dev/null +++ b/crates/core/src/token/validate.rs @@ -0,0 +1,213 @@ +// 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 +//! Token provider types. + +use chrono::Utc; + +pub use openstack_keystone_core_types::token::*; + +use crate::identity::IdentityApi; +use crate::keystone::ServiceState; +use crate::resource::ResourceApi; +use crate::token::error::TokenProviderError; +use crate::trust::TrustApi; + +/// Validate the token scope. +/// +/// Validate the scope validity of the token scope. For a project scoped +/// tokens this will raise an error when the project is disabled. For +/// domain scoped token the domain must be active. +pub async fn validate_token_scope( + token: &Token, + _state: &ServiceState, +) -> Result<(), TokenProviderError> { + match token { + Token::ApplicationCredential(data) => { + if !data + .project + .as_ref() + .ok_or(TokenProviderError::ScopeMissing)? + .enabled + { + return Err(TokenProviderError::ProjectDisabled(data.project_id.clone())); + } + if data + .application_credential + .as_ref() + .is_none_or(|ac| ac.project_id != data.project_id) + { + return Err(TokenProviderError::ApplicationCredentialScopeMismatch); + } + } + Token::DomainScope(data) => { + if !data + .domain + .as_ref() + .ok_or(TokenProviderError::ScopeMissing)? + .enabled + { + return Err(TokenProviderError::DomainDisabled(data.domain_id.clone())); + } + } + Token::FederationDomainScope(data) => { + if !data + .domain + .as_ref() + .ok_or(TokenProviderError::ScopeMissing)? + .enabled + { + return Err(TokenProviderError::DomainDisabled(data.domain_id.clone())); + } + } + Token::FederationProjectScope(data) => { + if !data + .project + .as_ref() + .ok_or(TokenProviderError::ScopeMissing)? + .enabled + { + return Err(TokenProviderError::ProjectDisabled(data.project_id.clone())); + } + } + Token::FederationUnscoped(_) => {} + Token::ProjectScope(data) => { + if !data + .project + .as_ref() + .ok_or(TokenProviderError::ScopeMissing)? + .enabled + { + return Err(TokenProviderError::ProjectDisabled(data.project_id.clone())); + } + } + Token::Restricted(data) => { + if !data + .project + .as_ref() + .ok_or(TokenProviderError::ScopeMissing)? + .enabled + { + return Err(TokenProviderError::ProjectDisabled(data.project_id.clone())); + } + } + Token::SystemScope(_data) => {} + Token::Trust(data) => { + if !data + .project + .as_ref() + .ok_or(TokenProviderError::ScopeMissing)? + .enabled + { + return Err(TokenProviderError::ProjectDisabled(data.project_id.clone())); + } + } + Token::Unscoped(_) => {} + } + Ok(()) +} + +/// Validate the token subject. +/// +/// Perform checks for the token subject: +/// +/// - user is enabled +/// - user domain is enabled +/// - application credential is not expired +pub async fn validate_token_subject( + token: &Token, + state: &ServiceState, +) -> Result<(), TokenProviderError> { + let user_domain_id: String; + if let Some(user) = token.user() { + // The "user" must be active + if !user.enabled { + return Err(TokenProviderError::UserDisabled(user.id.clone())); + } + + // Ensure user domain is enabled + if !state + .provider + .get_resource_provider() + .get_domain_enabled(state, &user.domain_id) + .await? + { + return Err(TokenProviderError::UserDomainDisabled); + } + + user_domain_id = user.domain_id.clone(); + } else { + return Err(TokenProviderError::SubjectMissing); + } + + match token { + Token::ApplicationCredential(data) => { + // Check whether application credential is expired + if data + .application_credential + .as_ref() + .and_then(|ac| ac.expires_at) + .is_some_and(|expiry| expiry < Utc::now()) + { + return Err(TokenProviderError::Expired); + } + } + Token::DomainScope(_data) => {} + Token::FederationDomainScope(_data) => {} + Token::FederationProjectScope(_data) => {} + Token::FederationUnscoped(_data) => {} + Token::ProjectScope(_data) => {} + Token::Restricted(_data) => {} + Token::SystemScope(_data) => {} + Token::Trust(data) => { + // Validate the trust chain + state + .provider + .get_trust_provider() + .validate_trust_delegation_chain( + state, + data.trust + .as_ref() + .ok_or(TokenProviderError::SubjectMissing)?, + ) + .await?; + // Validate trustor and trustee + if let Some(trust) = &data.trust { + if data.user_id != trust.trustee_user_id { + return Err(TokenProviderError::UserIsNotTrustee); + } + + // Resolve and verify trustor domain is enabled + let trustor_domain_id = state + .provider + .get_identity_provider() + .get_user_domain_id(state, &trust.trustor_user_id) + .await?; + + if user_domain_id != trustor_domain_id + && !state + .provider + .get_resource_provider() + .get_domain_enabled(state, &trustor_domain_id) + .await? + { + return Err(TokenProviderError::TrustorDomainDisabled); + } + } else { + return Err(TokenProviderError::SubjectMissing); + } + } + Token::Unscoped(_data) => {} + } + Ok(()) +} diff --git a/crates/core/src/trust/api/error.rs b/crates/core/src/trust/api/error.rs deleted file mode 100644 index f88a07c1..00000000 --- a/crates/core/src/trust/api/error.rs +++ /dev/null @@ -1,29 +0,0 @@ -// 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 - -use crate::api::error::KeystoneApiError; -use crate::trust::TrustProviderError; - -impl From for KeystoneApiError { - fn from(source: TrustProviderError) -> Self { - match source { - TrustProviderError::Conflict(x) => Self::Conflict(x), - TrustProviderError::ExpirationImpossible => Self::forbidden(source), - TrustProviderError::RedelegatedRolesNotAvailable => Self::forbidden(source), - TrustProviderError::RedelegationDeepnessExceed { .. } => Self::forbidden(source), - TrustProviderError::RemainingUsesExceed => Self::forbidden(source), - other => Self::InternalError(other.to_string()), - } - } -} diff --git a/crates/core/src/trust/backend.rs b/crates/core/src/trust/backend.rs index c51a27a0..85e8e914 100644 --- a/crates/core/src/trust/backend.rs +++ b/crates/core/src/trust/backend.rs @@ -14,8 +14,10 @@ //! Trust provider Backend trait. use async_trait::async_trait; +use openstack_keystone_core_types::trust::*; + use crate::keystone::ServiceState; -use crate::trust::{TrustProviderError, types::*}; +use crate::trust::TrustProviderError; /// TrustBackend trait. /// diff --git a/crates/core/src/trust/error.rs b/crates/core/src/trust/error.rs index 797c608d..e6455bc1 100644 --- a/crates/core/src/trust/error.rs +++ b/crates/core/src/trust/error.rs @@ -12,87 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 //! # Trust Error -use thiserror::Error; - -use crate::error::BuilderError; - -/// Trust extension error. -#[derive(Error, Debug)] -pub enum TrustProviderError { - /// Supported authentication error. - #[error(transparent)] - AuthenticationInfo { - /// The source of the error. - #[from] - source: crate::auth::AuthenticationError, - }, - - /// Conflict. - #[error("conflict: {0}")] - Conflict(String), - - /// Driver error. - #[error("backend driver error: {0}")] - Driver(String), - - /// Trust expiration is more than the redelegated trust can provide. - #[error("requested expiration is more than the redelegated trust can provide")] - ExpirationImpossible, - - /// DateTime parsing error. - #[error("error parsing int column as datetime: {expires_at}")] - ExpirationDateTimeParse { id: String, expires_at: i64 }, - - /// Relegated trust does not allow impersonation. - #[error( - "impersonation is not allowed because redelegated trust does not specify impersonation" - )] - RedelegatedImpersonationNotAllowed, - - /// Relegation trust must not add new roles. - #[error("some of the requested roles are not in the redelegated trust")] - RedelegatedRolesNotAvailable, - - /// Redelegation chain is longer than allowed. - #[error("redelegation depth of {length} is out of allowed range [0..{max_depth}]")] - RedelegationDeepnessExceed { length: usize, max_depth: usize }, - - /// Remaining uses of the trust is exceeded. - #[error("remaining uses exceed")] - RemainingUsesExceed, - - /// Remaining uses must be unset to redelegate a trust. - #[error("remaining uses is set while it must not be set in order to redelegate a trust")] - RemainingUsesMustBeUnset, - - /// Role provider error. - #[error(transparent)] - RoleProvider { - /// The source of the error. - #[from] - source: crate::role::RoleProviderError, - }, - - /// (de)serialization error. - #[error(transparent)] - Serde { - /// The source of the error. - #[from] - source: serde_json::Error, - }, - - /// Structures builder error. - #[error(transparent)] - StructBuilder { - /// The source of the error. - #[from] - source: BuilderError, - }, - - /// Unsupported driver. - #[error("unsupported driver `{0}` for the trust provider")] - UnsupportedDriver(String), -} +pub use openstack_keystone_core_types::trust::TrustProviderError; impl From for TrustProviderError { fn from(source: crate::error::DatabaseError) -> Self { diff --git a/crates/core/src/trust/mock.rs b/crates/core/src/trust/mock.rs index 40e6a9c8..4707c1ae 100644 --- a/crates/core/src/trust/mock.rs +++ b/crates/core/src/trust/mock.rs @@ -15,7 +15,9 @@ use async_trait::async_trait; use mockall::mock; -use crate::trust::{TrustApi, TrustProviderError, types::*}; +use openstack_keystone_core_types::trust::*; + +use crate::trust::{TrustApi, TrustProviderError}; use crate::keystone::ServiceState; diff --git a/crates/core/src/trust/mod.rs b/crates/core/src/trust/mod.rs index b7b8c082..e4aa0746 100644 --- a/crates/core/src/trust/mod.rs +++ b/crates/core/src/trust/mod.rs @@ -53,14 +53,14 @@ use async_trait::async_trait; -#[cfg(feature = "api")] -pub mod api; +use openstack_keystone_core_types::trust::*; + pub mod backend; pub mod error; #[cfg(any(test, feature = "mock"))] mod mock; +mod provider_api; pub mod service; -pub mod types; use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; @@ -70,7 +70,7 @@ use openstack_keystone_config::Config; pub use error::TrustProviderError; #[cfg(any(test, feature = "mock"))] pub use mock::MockTrustProvider; -pub use types::*; +pub use provider_api::TrustApi; /// Trust provider. pub enum TrustProvider { diff --git a/crates/core/src/trust/types/provider.rs b/crates/core/src/trust/provider_api.rs similarity index 94% rename from crates/core/src/trust/types/provider.rs rename to crates/core/src/trust/provider_api.rs index 93d2236c..f94bac6e 100644 --- a/crates/core/src/trust/types/provider.rs +++ b/crates/core/src/trust/provider_api.rs @@ -15,8 +15,10 @@ //! # Trust provider interface use async_trait::async_trait; +use openstack_keystone_core_types::trust::*; + use crate::keystone::ServiceState; -use crate::trust::{TrustProviderError, types::*}; +use crate::trust::TrustProviderError; /// Trust extension provider interface. #[async_trait] diff --git a/crates/core/src/trust/service.rs b/crates/core/src/trust/service.rs index dc9f590b..b8c9bbcf 100644 --- a/crates/core/src/trust/service.rs +++ b/crates/core/src/trust/service.rs @@ -21,11 +21,14 @@ use async_trait::async_trait; use chrono::{DateTime, Utc}; use tracing::debug; +use openstack_keystone_config::Config; +use openstack_keystone_core_types::role::*; +use openstack_keystone_core_types::trust::*; + use crate::keystone::ServiceState; use crate::plugin_manager::PluginManagerApi; -use crate::role::{RoleApi, types::Role}; -use crate::trust::{TrustProviderError, backend::TrustBackend, types::*}; -use openstack_keystone_config::Config; +use crate::role::RoleApi; +use crate::trust::{TrustApi, TrustProviderError, backend::TrustBackend}; /// Trust provider. pub struct TrustService { @@ -60,7 +63,7 @@ impl TrustApi for TrustService { .get_role_provider() .list_roles( state, - &crate::role::types::RoleListParameters { + &RoleListParameters { domain_id: Some(None), ..Default::default() }, @@ -110,7 +113,7 @@ impl TrustApi for TrustService { .get_role_provider() .list_roles( state, - &crate::role::types::RoleListParameters { + &RoleListParameters { domain_id: Some(None), ..Default::default() }, @@ -233,9 +236,11 @@ mod tests { use chrono::{DateTime, Utc}; use std::sync::Arc; + use openstack_keystone_core_types::role::*; + use super::*; use crate::provider::Provider; - use crate::role::{MockRoleProvider, types::*}; + use crate::role::MockRoleProvider; use crate::tests::get_mocked_state; use crate::trust::backend::MockTrustBackend; diff --git a/crates/federation-sql/Cargo.toml b/crates/federation-sql/Cargo.toml index cc97ce4e..e0f179ed 100644 --- a/crates/federation-sql/Cargo.toml +++ b/crates/federation-sql/Cargo.toml @@ -14,6 +14,7 @@ exclude.workspace = true async-trait.workspace = true chrono = { workspace = true, features = ["now"] } openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } sea-orm.workspace = true serde_json.workspace = true tracing.workspace = true diff --git a/crates/federation-sql/src/auth_state.rs b/crates/federation-sql/src/auth_state.rs index 2bce46c6..57caf700 100644 --- a/crates/federation-sql/src/auth_state.rs +++ b/crates/federation-sql/src/auth_state.rs @@ -12,9 +12,9 @@ // // SPDX-License-Identifier: Apache-2.0 -use openstack_keystone_core::common::types::Scope; use openstack_keystone_core::federation::error::FederationProviderError; -use openstack_keystone_core::federation::types::*; +use openstack_keystone_core_types::federation::*; +use openstack_keystone_core_types::scope::Scope; use crate::entity::federated_auth_state as db_federated_auth_state; diff --git a/crates/federation-sql/src/auth_state/create.rs b/crates/federation-sql/src/auth_state/create.rs index d06eaed4..4220a080 100644 --- a/crates/federation-sql/src/auth_state/create.rs +++ b/crates/federation-sql/src/auth_state/create.rs @@ -16,7 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::federation::{FederationProviderError, types::AuthState}; +use openstack_keystone_core::federation::FederationProviderError; +use openstack_keystone_core_types::federation::AuthState; use crate::entity::federated_auth_state as db_federated_auth_state; diff --git a/crates/federation-sql/src/auth_state/get.rs b/crates/federation-sql/src/auth_state/get.rs index 79b1b725..cdc2f705 100644 --- a/crates/federation-sql/src/auth_state/get.rs +++ b/crates/federation-sql/src/auth_state/get.rs @@ -16,7 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::federation::{FederationProviderError, types::AuthState}; +use openstack_keystone_core::federation::FederationProviderError; +use openstack_keystone_core_types::federation::AuthState; use crate::entity::{ federated_auth_state as db_federated_auth_state, diff --git a/crates/federation-sql/src/identity_provider.rs b/crates/federation-sql/src/identity_provider.rs index 039a736e..e31187ed 100644 --- a/crates/federation-sql/src/identity_provider.rs +++ b/crates/federation-sql/src/identity_provider.rs @@ -13,7 +13,7 @@ // SPDX-License-Identifier: Apache-2.0 use openstack_keystone_core::federation::error::FederationProviderError; -use openstack_keystone_core::federation::types::*; +use openstack_keystone_core_types::federation::*; use crate::entity::federated_identity_provider as db_federated_identity_provider; diff --git a/crates/federation-sql/src/identity_provider/create.rs b/crates/federation-sql/src/identity_provider/create.rs index 041f96d1..79c0629b 100644 --- a/crates/federation-sql/src/identity_provider/create.rs +++ b/crates/federation-sql/src/identity_provider/create.rs @@ -18,10 +18,8 @@ use sea_orm::sea_query::OnConflict; use uuid::Uuid; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::federation::{ - FederationProviderError, - types::{IdentityProvider, IdentityProviderCreate}, -}; +use openstack_keystone_core::federation::FederationProviderError; +use openstack_keystone_core_types::federation::*; use crate::entity::{ federated_identity_provider as db_federated_identity_provider, diff --git a/crates/federation-sql/src/identity_provider/get.rs b/crates/federation-sql/src/identity_provider/get.rs index bc8478b9..76243c94 100644 --- a/crates/federation-sql/src/identity_provider/get.rs +++ b/crates/federation-sql/src/identity_provider/get.rs @@ -16,7 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::federation::{FederationProviderError, types::IdentityProvider}; +use openstack_keystone_core::federation::FederationProviderError; +use openstack_keystone_core_types::federation::*; use crate::entity::{ federated_identity_provider as db_federated_identity_provider, diff --git a/crates/federation-sql/src/identity_provider/list.rs b/crates/federation-sql/src/identity_provider/list.rs index a9bc3c79..2421ff70 100644 --- a/crates/federation-sql/src/identity_provider/list.rs +++ b/crates/federation-sql/src/identity_provider/list.rs @@ -18,10 +18,8 @@ use sea_orm::query::*; use sea_orm::{Cursor, SelectModel}; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::federation::{ - FederationProviderError, - types::{IdentityProvider, IdentityProviderListParameters}, -}; +use openstack_keystone_core::federation::FederationProviderError; +use openstack_keystone_core_types::federation::*; use crate::entity::{ federated_identity_provider as db_federated_identity_provider, diff --git a/crates/federation-sql/src/identity_provider/update.rs b/crates/federation-sql/src/identity_provider/update.rs index e69203d5..4483d0c9 100644 --- a/crates/federation-sql/src/identity_provider/update.rs +++ b/crates/federation-sql/src/identity_provider/update.rs @@ -16,10 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::federation::{ - FederationProviderError, - types::{IdentityProvider, IdentityProviderUpdate}, -}; +use openstack_keystone_core::federation::FederationProviderError; +use openstack_keystone_core_types::federation::*; use crate::entity::{ federated_identity_provider as db_federated_identity_provider, diff --git a/crates/federation-sql/src/lib.rs b/crates/federation-sql/src/lib.rs index fc70f34f..b4fe6f0d 100644 --- a/crates/federation-sql/src/lib.rs +++ b/crates/federation-sql/src/lib.rs @@ -14,10 +14,9 @@ //! OpenStack Keystone SQL driver for the federation provider use async_trait::async_trait; -use openstack_keystone_core::federation::{ - FederationProviderError, backend::FederationBackend, types::*, -}; +use openstack_keystone_core::federation::{FederationProviderError, backend::FederationBackend}; use openstack_keystone_core::keystone::ServiceState; +use openstack_keystone_core_types::federation::*; mod auth_state; pub mod entity; diff --git a/crates/federation-sql/src/mapping.rs b/crates/federation-sql/src/mapping.rs index 2d783634..9675f7ad 100644 --- a/crates/federation-sql/src/mapping.rs +++ b/crates/federation-sql/src/mapping.rs @@ -13,7 +13,7 @@ // SPDX-License-Identifier: Apache-2.0 use openstack_keystone_core::federation::error::FederationProviderError; -use openstack_keystone_core::federation::types::*; +use openstack_keystone_core_types::federation::*; use crate::entity::{ federated_mapping as db_federated_mapping, sea_orm_active_enums::MappingType as db_mapping_type, diff --git a/crates/federation-sql/src/mapping/create.rs b/crates/federation-sql/src/mapping/create.rs index 5745f374..26d2a4cc 100644 --- a/crates/federation-sql/src/mapping/create.rs +++ b/crates/federation-sql/src/mapping/create.rs @@ -16,7 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::federation::{FederationProviderError, types::Mapping}; +use openstack_keystone_core::federation::FederationProviderError; +use openstack_keystone_core_types::federation::*; use crate::entity::federated_mapping as db_federated_mapping; @@ -98,7 +99,7 @@ mod tests { use sea_orm::{DatabaseBackend, MockDatabase, Transaction}; use serde_json::json; - use openstack_keystone_core::federation::types::MappingType; + use openstack_keystone_core_types::federation::*; use super::super::tests::get_mapping_mock; use super::*; diff --git a/crates/federation-sql/src/mapping/get.rs b/crates/federation-sql/src/mapping/get.rs index 20225e25..606a463b 100644 --- a/crates/federation-sql/src/mapping/get.rs +++ b/crates/federation-sql/src/mapping/get.rs @@ -16,7 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::federation::{FederationProviderError, types::Mapping}; +use openstack_keystone_core::federation::FederationProviderError; +use openstack_keystone_core_types::federation::*; use crate::entity::{ federated_mapping as db_federated_mapping, prelude::FederatedMapping as DbFederatedMapping, diff --git a/crates/federation-sql/src/mapping/list.rs b/crates/federation-sql/src/mapping/list.rs index 8fb9e483..2046a14c 100644 --- a/crates/federation-sql/src/mapping/list.rs +++ b/crates/federation-sql/src/mapping/list.rs @@ -18,10 +18,8 @@ use sea_orm::query::*; use sea_orm::{Cursor, SelectModel}; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::federation::{ - FederationProviderError, - types::{Mapping, MappingListParameters}, -}; +use openstack_keystone_core::federation::FederationProviderError; +use openstack_keystone_core_types::federation::{Mapping, MappingListParameters}; use crate::entity::{ federated_mapping as db_federated_mapping, prelude::FederatedMapping as DbFederatedMapping, @@ -77,7 +75,7 @@ pub async fn list( mod tests { use sea_orm::{DatabaseBackend, MockDatabase, QueryOrder, Transaction, sea_query::*}; - use openstack_keystone_core::federation::types::mapping::MappingType; + use openstack_keystone_core_types::federation::MappingType; use super::super::tests::get_mapping_mock; use super::*; diff --git a/crates/federation-sql/src/mapping/update.rs b/crates/federation-sql/src/mapping/update.rs index d2434bb6..fd6a539a 100644 --- a/crates/federation-sql/src/mapping/update.rs +++ b/crates/federation-sql/src/mapping/update.rs @@ -16,10 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::federation::{ - FederationProviderError, - types::{Mapping, MappingUpdate}, -}; +use openstack_keystone_core::federation::FederationProviderError; +use openstack_keystone_core_types::federation::{Mapping, MappingUpdate}; use crate::entity::{ federated_mapping as db_federated_mapping, prelude::FederatedMapping as DbFederatedMapping, @@ -97,7 +95,7 @@ mod tests { use sea_orm::{DatabaseBackend, MockDatabase, MockExecResult, Transaction}; use serde_json::json; - use openstack_keystone_core::federation::types::mapping::MappingType; + use openstack_keystone_core_types::federation::MappingType; use super::super::tests::get_mapping_mock; use super::*; diff --git a/crates/identity-sql/Cargo.toml b/crates/identity-sql/Cargo.toml index 52376f87..6fcdfd56 100644 --- a/crates/identity-sql/Cargo.toml +++ b/crates/identity-sql/Cargo.toml @@ -15,6 +15,7 @@ async-trait.workspace = true chrono = { workspace = true, features = ["now"] } openstack-keystone-config = { version = "0.1", path = "../config" } openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } sea-orm.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/crates/identity-sql/src/authenticate.rs b/crates/identity-sql/src/authenticate.rs index 230f0828..04ed52b0 100644 --- a/crates/identity-sql/src/authenticate.rs +++ b/crates/identity-sql/src/authenticate.rs @@ -19,10 +19,8 @@ use tracing::info; use openstack_keystone_config::Config; use openstack_keystone_core::auth::{AuthenticatedInfo, AuthenticationError}; use openstack_keystone_core::common::password_hashing; -use openstack_keystone_core::identity::{ - IdentityProviderError, - types::{UserPasswordAuthRequest, UserResponseBuilder}, -}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::{UserPasswordAuthRequest, UserResponseBuilder}; use crate::entity::{local_user as db_local_user, password as db_password}; use crate::local_user; @@ -90,7 +88,10 @@ pub async fn authenticate_by_password( ))?; // Verify the password - if !password_hashing::verify_password(config, &auth.password, expected_hash).await? { + if !password_hashing::verify_password(config, &auth.password, expected_hash) + .await + .map_err(IdentityProviderError::password_hash)? + { return Err(AuthenticationError::UserNameOrPasswordWrong)?; } // Check if expired password exempt is on @@ -180,7 +181,7 @@ mod tests { use sea_orm::{DatabaseBackend, MockDatabase, Transaction}; use tracing_test::traced_test; - use openstack_keystone_core::identity::types::UserOptions; + use openstack_keystone_core_types::identity::UserOptions; use super::*; use crate::entity::local_user as db_local_user; diff --git a/crates/identity-sql/src/federated_user.rs b/crates/identity-sql/src/federated_user.rs index 854e05db..cf25e3f3 100644 --- a/crates/identity-sql/src/federated_user.rs +++ b/crates/identity-sql/src/federated_user.rs @@ -12,7 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 -use openstack_keystone_core::identity::types::*; +use openstack_keystone_core_types::identity::*; use crate::entity::federated_user as db_federated_user; diff --git a/crates/identity-sql/src/group.rs b/crates/identity-sql/src/group.rs index d3c29a48..db249699 100644 --- a/crates/identity-sql/src/group.rs +++ b/crates/identity-sql/src/group.rs @@ -14,7 +14,7 @@ use serde_json::{Value, json}; -use openstack_keystone_core::identity::types::Group; +use openstack_keystone_core_types::identity::Group; use crate::entity::group; diff --git a/crates/identity-sql/src/group/create.rs b/crates/identity-sql/src/group/create.rs index b244a20c..e9d61c5e 100644 --- a/crates/identity-sql/src/group/create.rs +++ b/crates/identity-sql/src/group/create.rs @@ -17,10 +17,8 @@ use sea_orm::entity::*; use serde_json::json; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity::{ - IdentityProviderError, - types::{Group, GroupCreate}, -}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::{Group, GroupCreate}; use crate::entity::group; diff --git a/crates/identity-sql/src/group/get.rs b/crates/identity-sql/src/group/get.rs index d7a8b866..80c01082 100644 --- a/crates/identity-sql/src/group/get.rs +++ b/crates/identity-sql/src/group/get.rs @@ -16,7 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity::{IdentityProviderError, types::Group}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::Group; use crate::entity::prelude::Group as DbGroup; diff --git a/crates/identity-sql/src/group/list.rs b/crates/identity-sql/src/group/list.rs index 940f4019..ca1f6490 100644 --- a/crates/identity-sql/src/group/list.rs +++ b/crates/identity-sql/src/group/list.rs @@ -17,10 +17,8 @@ use sea_orm::entity::*; use sea_orm::query::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity::{ - IdentityProviderError, - types::{Group, GroupListParameters}, -}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::{Group, GroupListParameters}; use crate::entity::{group, prelude::Group as DbGroup}; @@ -53,7 +51,7 @@ mod tests { use sea_orm::{DatabaseBackend, MockDatabase, Transaction}; use serde_json::json; - use openstack_keystone_core::identity::types::group::GroupListParametersBuilder; + use openstack_keystone_core_types::identity::GroupListParametersBuilder; use crate::entity::group; diff --git a/crates/identity-sql/src/lib.rs b/crates/identity-sql/src/lib.rs index 7c500354..f82361d5 100644 --- a/crates/identity-sql/src/lib.rs +++ b/crates/identity-sql/src/lib.rs @@ -20,8 +20,8 @@ use chrono::{DateTime, Utc}; use openstack_keystone_core::auth::AuthenticatedInfo; use openstack_keystone_core::identity::IdentityProviderError; use openstack_keystone_core::identity::backend::IdentityBackend; -use openstack_keystone_core::identity::types::*; use openstack_keystone_core::keystone::ServiceState; +use openstack_keystone_core_types::identity::*; mod authenticate; pub mod entity; diff --git a/crates/identity-sql/src/local_user.rs b/crates/identity-sql/src/local_user.rs index 2bbc35e8..4253f43f 100644 --- a/crates/identity-sql/src/local_user.rs +++ b/crates/identity-sql/src/local_user.rs @@ -12,7 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 -use openstack_keystone_core::identity::types::*; +use openstack_keystone_core_types::identity::*; use crate::entity::local_user as db_local_user; diff --git a/crates/identity-sql/src/local_user/create.rs b/crates/identity-sql/src/local_user/create.rs index 9f7c6869..67604c7c 100644 --- a/crates/identity-sql/src/local_user/create.rs +++ b/crates/identity-sql/src/local_user/create.rs @@ -17,7 +17,8 @@ use sea_orm::entity::*; use openstack_keystone_config::Config; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity::{IdentityProviderError, types::UserCreate}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::UserCreate; use crate::entity::{local_user, user}; diff --git a/crates/identity-sql/src/nonlocal_user.rs b/crates/identity-sql/src/nonlocal_user.rs index 201b86d8..7e85ed95 100644 --- a/crates/identity-sql/src/nonlocal_user.rs +++ b/crates/identity-sql/src/nonlocal_user.rs @@ -12,7 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 -use openstack_keystone_core::identity::types::UserResponseBuilder; +use openstack_keystone_core_types::identity::UserResponseBuilder; use crate::entity::nonlocal_user as db_nonlocal_user; diff --git a/crates/identity-sql/src/password.rs b/crates/identity-sql/src/password.rs index 16967b68..d1b401ea 100644 --- a/crates/identity-sql/src/password.rs +++ b/crates/identity-sql/src/password.rs @@ -13,7 +13,8 @@ // SPDX-License-Identifier: Apache-2.0 use chrono::{DateTime, Utc}; -use openstack_keystone_core::identity::{IdentityProviderError, types::UserResponseBuilder}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::UserResponseBuilder; use crate::entity::password as db_password; diff --git a/crates/identity-sql/src/service_account/create.rs b/crates/identity-sql/src/service_account/create.rs index 95378923..30083caa 100644 --- a/crates/identity-sql/src/service_account/create.rs +++ b/crates/identity-sql/src/service_account/create.rs @@ -20,8 +20,9 @@ use uuid::Uuid; use openstack_keystone_config::Config; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity::types::get_user_last_active_at; -use openstack_keystone_core::identity::{IdentityProviderError, types::*}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core::identity::get_user_last_active_at; +use openstack_keystone_core_types::identity::*; use crate::entity::user as db_user; use crate::nonlocal_user; diff --git a/crates/identity-sql/src/service_account/get.rs b/crates/identity-sql/src/service_account/get.rs index 78e50a02..e5592fa3 100644 --- a/crates/identity-sql/src/service_account/get.rs +++ b/crates/identity-sql/src/service_account/get.rs @@ -15,10 +15,8 @@ use sea_orm::DatabaseConnection; use openstack_keystone_config::Config; -use openstack_keystone_core::identity::{ - IdentityProviderError, - types::{ServiceAccount, ServiceAccountBuilder}, -}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::{ServiceAccount, ServiceAccountBuilder}; use crate::nonlocal_user; use crate::user; @@ -75,7 +73,7 @@ mod tests { use sea_orm::{DatabaseBackend, MockDatabase}; use openstack_keystone_config::Config; - use openstack_keystone_core::identity::types::UserOptions; + use openstack_keystone_core_types::identity::UserOptions; use super::*; use crate::nonlocal_user::tests::get_nonlocal_user_mock; diff --git a/crates/identity-sql/src/user.rs b/crates/identity-sql/src/user.rs index 8888411b..fdbaf81d 100644 --- a/crates/identity-sql/src/user.rs +++ b/crates/identity-sql/src/user.rs @@ -16,7 +16,7 @@ use chrono::NaiveDate; use serde_json::Value; use tracing::error; -use openstack_keystone_core::identity::types::{UserOptions, UserResponseBuilder}; +use openstack_keystone_core_types::identity::{UserOptions, UserResponseBuilder}; use crate::entity::user as db_user; diff --git a/crates/identity-sql/src/user/create.rs b/crates/identity-sql/src/user/create.rs index c2785e5c..e4d62c05 100644 --- a/crates/identity-sql/src/user/create.rs +++ b/crates/identity-sql/src/user/create.rs @@ -14,7 +14,6 @@ use chrono::{DateTime, Utc}; use sea_orm::DatabaseConnection; -//use sea_orm::Iden; use sea_orm::entity::*; use sea_orm::{ConnectionTrait, TransactionTrait}; use serde_json::json; @@ -23,10 +22,8 @@ use uuid::Uuid; use openstack_keystone_config::Config; use openstack_keystone_core::common::password_hashing; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity::{ - IdentityProviderError, - types::{UserCreate, UserOptions, UserResponse, UserResponseBuilder, get_user_last_active_at}, -}; +use openstack_keystone_core::identity::{IdentityProviderError, get_user_last_active_at}; +use openstack_keystone_core_types::identity::*; use crate::entity::{ federated_user as db_federated_user, password as db_password, user as db_user, @@ -174,7 +171,9 @@ pub async fn create( let password_entry = password::create( &txn, local_user.id, - password_hashing::hash_password(conf, password).await?, + password_hashing::hash_password(conf, password) + .await + .map_err(IdentityProviderError::password_hash)?, None, ) .await?; @@ -196,9 +195,8 @@ mod tests { use sea_orm::{DatabaseBackend, MockDatabase, MockExecResult, Transaction}; use openstack_keystone_config::Config; - use openstack_keystone_core::identity::types::{ - UserCreateBuilder, - user::{FederationBuilder, FederationProtocol}, + use openstack_keystone_core_types::identity::{ + UserCreateBuilder, {FederationBuilder, FederationProtocol}, }; use super::*; diff --git a/crates/identity-sql/src/user/get.rs b/crates/identity-sql/src/user/get.rs index 806b13f7..b754507a 100644 --- a/crates/identity-sql/src/user/get.rs +++ b/crates/identity-sql/src/user/get.rs @@ -18,10 +18,8 @@ use sea_orm::query::*; use openstack_keystone_config::Config; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity::{ - IdentityProviderError, - types::{UserOptions, UserResponse, UserResponseBuilder}, -}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::{UserOptions, UserResponse, UserResponseBuilder}; use crate::entity::{ nonlocal_user as db_nonlocal_user, diff --git a/crates/identity-sql/src/user/list.rs b/crates/identity-sql/src/user/list.rs index 1d0e2017..1c992d1c 100644 --- a/crates/identity-sql/src/user/list.rs +++ b/crates/identity-sql/src/user/list.rs @@ -18,9 +18,9 @@ use sea_orm::query::*; use openstack_keystone_config::Config; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity::{ - IdentityProviderError, - types::{UserListParameters, UserOptions, UserResponse, UserResponseBuilder, UserType}, +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::{ + UserListParameters, UserOptions, UserResponse, UserResponseBuilder, UserType, }; use crate::entity::{ diff --git a/crates/identity-sql/src/user_group/list.rs b/crates/identity-sql/src/user_group/list.rs index 752bec07..67e095d2 100644 --- a/crates/identity-sql/src/user_group/list.rs +++ b/crates/identity-sql/src/user_group/list.rs @@ -18,7 +18,8 @@ use sea_orm::query::*; use sea_orm::sea_query::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity::{IdentityProviderError, types::Group}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::Group; use crate::entity::{ expiring_user_group_membership, group as db_group, prelude::Group as DbGroup, diff --git a/crates/identity-sql/src/user_option.rs b/crates/identity-sql/src/user_option.rs index a9f425b5..ab1ce4ea 100644 --- a/crates/identity-sql/src/user_option.rs +++ b/crates/identity-sql/src/user_option.rs @@ -12,7 +12,8 @@ // // SPDX-License-Identifier: Apache-2.0 -use openstack_keystone_core::identity::{IdentityProviderError, types::UserOptions}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::UserOptions; use crate::entity::user_option; @@ -134,7 +135,7 @@ impl UserOptionIntoModelIterator for UserOptions { #[cfg(test)] pub(crate) mod tests { - use openstack_keystone_core::identity::types::UserOptions; + use openstack_keystone_core_types::identity::UserOptions; use super::*; use crate::entity::user_option; diff --git a/crates/identity-sql/src/user_option/create.rs b/crates/identity-sql/src/user_option/create.rs index a4346bb2..d16cc2e6 100644 --- a/crates/identity-sql/src/user_option/create.rs +++ b/crates/identity-sql/src/user_option/create.rs @@ -16,7 +16,8 @@ use sea_orm::ConnectionTrait; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity::{IdentityProviderError, types::UserOptions}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::UserOptions; use crate::entity::prelude::UserOption as DbUserOption; use crate::entity::user_option as db_user_option; diff --git a/crates/identity-sql/src/user_option/list.rs b/crates/identity-sql/src/user_option/list.rs index 6dc9fd55..cd402091 100644 --- a/crates/identity-sql/src/user_option/list.rs +++ b/crates/identity-sql/src/user_option/list.rs @@ -17,7 +17,8 @@ use sea_orm::entity::*; use sea_orm::query::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity::{IdentityProviderError, types::UserOptions}; +use openstack_keystone_core::identity::IdentityProviderError; +use openstack_keystone_core_types::identity::UserOptions; use crate::entity::{prelude::UserOption as DbUserOptions, user_option}; diff --git a/crates/idmapping-sql/Cargo.toml b/crates/idmapping-sql/Cargo.toml index 0813ad31..4e2d60ea 100644 --- a/crates/idmapping-sql/Cargo.toml +++ b/crates/idmapping-sql/Cargo.toml @@ -13,6 +13,7 @@ exclude.workspace = true [dependencies] async-trait.workspace = true openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } sea-orm.workspace = true tracing.workspace = true diff --git a/crates/idmapping-sql/src/id_mapping.rs b/crates/idmapping-sql/src/id_mapping.rs index d1b867c6..16c4aa0f 100644 --- a/crates/idmapping-sql/src/id_mapping.rs +++ b/crates/idmapping-sql/src/id_mapping.rs @@ -12,7 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 -use openstack_keystone_core::identity_mapping::types::{IdMapping, IdMappingEntityType}; +use openstack_keystone_core_types::identity_mapping::{IdMapping, IdMappingEntityType}; use crate::entity::id_mapping as db_id_mapping; use crate::entity::sea_orm_active_enums::EntityType; diff --git a/crates/idmapping-sql/src/id_mapping/get.rs b/crates/idmapping-sql/src/id_mapping/get.rs index 723f7e3c..bb59319d 100644 --- a/crates/idmapping-sql/src/id_mapping/get.rs +++ b/crates/idmapping-sql/src/id_mapping/get.rs @@ -17,7 +17,8 @@ use sea_orm::entity::*; use sea_orm::query::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::identity_mapping::{IdentityMappingProviderError, types::IdMapping}; +use openstack_keystone_core::identity_mapping::IdentityMappingProviderError; +use openstack_keystone_core_types::identity_mapping::IdMapping; use crate::entity::{ id_mapping, prelude::IdMapping as DbIdMapping, sea_orm_active_enums::EntityType, diff --git a/crates/idmapping-sql/src/lib.rs b/crates/idmapping-sql/src/lib.rs index 1cec7e36..a6ba6aba 100644 --- a/crates/idmapping-sql/src/lib.rs +++ b/crates/idmapping-sql/src/lib.rs @@ -16,8 +16,8 @@ use async_trait::async_trait; use openstack_keystone_core::identity_mapping::IdentityMappingProviderError; use openstack_keystone_core::identity_mapping::backend::IdentityMappingBackend; -use openstack_keystone_core::identity_mapping::types::*; use openstack_keystone_core::keystone::ServiceState; +use openstack_keystone_core_types::identity_mapping::*; pub mod entity; mod id_mapping; diff --git a/crates/k8s-auth-sql/Cargo.toml b/crates/k8s-auth-sql/Cargo.toml index 59f4f765..1f21bc64 100644 --- a/crates/k8s-auth-sql/Cargo.toml +++ b/crates/k8s-auth-sql/Cargo.toml @@ -13,6 +13,7 @@ exclude.workspace = true [dependencies] async-trait.workspace = true openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } sea-orm.workspace = true tracing.workspace = true uuid = { workspace = true, features = ["v4"] } diff --git a/crates/k8s-auth-sql/src/instance.rs b/crates/k8s-auth-sql/src/instance.rs index b5d90fbd..e68911cc 100644 --- a/crates/k8s-auth-sql/src/instance.rs +++ b/crates/k8s-auth-sql/src/instance.rs @@ -14,7 +14,7 @@ use sea_orm::entity::*; -use openstack_keystone_core::k8s_auth::types::*; +use openstack_keystone_core_types::k8s_auth::*; use crate::entity::kubernetes_auth_instance as db_k8s_auth_instance; @@ -99,7 +99,7 @@ impl db_k8s_auth_instance::Model { pub(crate) mod tests { use sea_orm::entity::*; - use openstack_keystone_core::k8s_auth::types::*; + use openstack_keystone_core_types::k8s_auth::*; use crate::entity::kubernetes_auth_instance; diff --git a/crates/k8s-auth-sql/src/instance/create.rs b/crates/k8s-auth-sql/src/instance/create.rs index 07812b9a..47e41b83 100644 --- a/crates/k8s-auth-sql/src/instance/create.rs +++ b/crates/k8s-auth-sql/src/instance/create.rs @@ -17,10 +17,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::k8s_auth::{ - K8sAuthProviderError, - types::{K8sAuthInstance, K8sAuthInstanceCreate}, -}; +use openstack_keystone_core::k8s_auth::K8sAuthProviderError; +use openstack_keystone_core_types::k8s_auth::{K8sAuthInstance, K8sAuthInstanceCreate}; use crate::entity::kubernetes_auth_instance; diff --git a/crates/k8s-auth-sql/src/instance/get.rs b/crates/k8s-auth-sql/src/instance/get.rs index 1b008fbf..9771e2de 100644 --- a/crates/k8s-auth-sql/src/instance/get.rs +++ b/crates/k8s-auth-sql/src/instance/get.rs @@ -16,7 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::k8s_auth::{K8sAuthProviderError, types::K8sAuthInstance}; +use openstack_keystone_core::k8s_auth::K8sAuthProviderError; +use openstack_keystone_core_types::k8s_auth::K8sAuthInstance; use crate::entity::prelude::KubernetesAuthInstance; diff --git a/crates/k8s-auth-sql/src/instance/list.rs b/crates/k8s-auth-sql/src/instance/list.rs index ee3e2abf..3f83527e 100644 --- a/crates/k8s-auth-sql/src/instance/list.rs +++ b/crates/k8s-auth-sql/src/instance/list.rs @@ -19,10 +19,8 @@ use sea_orm::query::*; use sea_orm::{Cursor, SelectModel}; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::k8s_auth::{ - K8sAuthProviderError, - types::{K8sAuthInstance, K8sAuthInstanceListParameters}, -}; +use openstack_keystone_core::k8s_auth::K8sAuthProviderError; +use openstack_keystone_core_types::k8s_auth::{K8sAuthInstance, K8sAuthInstanceListParameters}; use crate::entity::{kubernetes_auth_instance, prelude::KubernetesAuthInstance}; diff --git a/crates/k8s-auth-sql/src/instance/update.rs b/crates/k8s-auth-sql/src/instance/update.rs index 66b3a143..2fb1f203 100644 --- a/crates/k8s-auth-sql/src/instance/update.rs +++ b/crates/k8s-auth-sql/src/instance/update.rs @@ -18,10 +18,8 @@ use sea_orm::TransactionTrait; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::k8s_auth::{ - K8sAuthProviderError, - types::{K8sAuthInstance, K8sAuthInstanceUpdate}, -}; +use openstack_keystone_core::k8s_auth::K8sAuthProviderError; +use openstack_keystone_core_types::k8s_auth::{K8sAuthInstance, K8sAuthInstanceUpdate}; use crate::entity::prelude::KubernetesAuthInstance; diff --git a/crates/k8s-auth-sql/src/lib.rs b/crates/k8s-auth-sql/src/lib.rs index b7fa4f3d..c988092d 100644 --- a/crates/k8s-auth-sql/src/lib.rs +++ b/crates/k8s-auth-sql/src/lib.rs @@ -17,8 +17,8 @@ use async_trait::async_trait; use openstack_keystone_core::k8s_auth::backend::K8sAuthBackend; use openstack_keystone_core::k8s_auth::error::K8sAuthProviderError; -use openstack_keystone_core::k8s_auth::types::*; use openstack_keystone_core::keystone::ServiceState; +use openstack_keystone_core_types::k8s_auth::*; pub mod entity; mod instance; diff --git a/crates/k8s-auth-sql/src/role.rs b/crates/k8s-auth-sql/src/role.rs index 6d3d7bcc..746ce14f 100644 --- a/crates/k8s-auth-sql/src/role.rs +++ b/crates/k8s-auth-sql/src/role.rs @@ -14,7 +14,7 @@ use sea_orm::entity::*; -use openstack_keystone_core::k8s_auth::types::*; +use openstack_keystone_core_types::k8s_auth::*; use crate::entity::kubernetes_auth_role; @@ -127,7 +127,7 @@ impl kubernetes_auth_role::Model { pub(crate) mod tests { use sea_orm::entity::*; - use openstack_keystone_core::k8s_auth::types::*; + use openstack_keystone_core_types::k8s_auth::*; use crate::entity::kubernetes_auth_role; diff --git a/crates/k8s-auth-sql/src/role/create.rs b/crates/k8s-auth-sql/src/role/create.rs index cf97dba4..92aeb372 100644 --- a/crates/k8s-auth-sql/src/role/create.rs +++ b/crates/k8s-auth-sql/src/role/create.rs @@ -17,10 +17,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::k8s_auth::{ - K8sAuthProviderError, - types::{K8sAuthRole, K8sAuthRoleCreate}, -}; +use openstack_keystone_core::k8s_auth::K8sAuthProviderError; +use openstack_keystone_core_types::k8s_auth::{K8sAuthRole, K8sAuthRoleCreate}; use crate::entity::kubernetes_auth_role; diff --git a/crates/k8s-auth-sql/src/role/get.rs b/crates/k8s-auth-sql/src/role/get.rs index c37c599f..bceec034 100644 --- a/crates/k8s-auth-sql/src/role/get.rs +++ b/crates/k8s-auth-sql/src/role/get.rs @@ -16,7 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::k8s_auth::{K8sAuthProviderError, types::K8sAuthRole}; +use openstack_keystone_core::k8s_auth::K8sAuthProviderError; +use openstack_keystone_core_types::k8s_auth::K8sAuthRole; use crate::entity::prelude::KubernetesAuthRole; diff --git a/crates/k8s-auth-sql/src/role/list.rs b/crates/k8s-auth-sql/src/role/list.rs index 9b9fcc93..aeedd9f7 100644 --- a/crates/k8s-auth-sql/src/role/list.rs +++ b/crates/k8s-auth-sql/src/role/list.rs @@ -19,10 +19,8 @@ use sea_orm::query::*; use sea_orm::{Cursor, SelectModel}; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::k8s_auth::{ - K8sAuthProviderError, - types::{K8sAuthRole, K8sAuthRoleListParameters}, -}; +use openstack_keystone_core::k8s_auth::K8sAuthProviderError; +use openstack_keystone_core_types::k8s_auth::{K8sAuthRole, K8sAuthRoleListParameters}; use crate::entity::{kubernetes_auth_role, prelude::KubernetesAuthRole}; diff --git a/crates/k8s-auth-sql/src/role/update.rs b/crates/k8s-auth-sql/src/role/update.rs index e5cc7cc1..e842e005 100644 --- a/crates/k8s-auth-sql/src/role/update.rs +++ b/crates/k8s-auth-sql/src/role/update.rs @@ -18,10 +18,8 @@ use sea_orm::TransactionTrait; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::k8s_auth::{ - K8sAuthProviderError, - types::{K8sAuthRole, K8sAuthRoleUpdate}, -}; +use openstack_keystone_core::k8s_auth::K8sAuthProviderError; +use openstack_keystone_core_types::k8s_auth::{K8sAuthRole, K8sAuthRoleUpdate}; use crate::entity::prelude::KubernetesAuthRole; diff --git a/crates/keystone/Cargo.toml b/crates/keystone/Cargo.toml index daf92c5c..287473c3 100644 --- a/crates/keystone/Cargo.toml +++ b/crates/keystone/Cargo.toml @@ -28,12 +28,13 @@ clap = { workspace = true, features = ["derive"] } color-eyre.workspace = true derive_builder.workspace = true eyre.workspace = true -openstack-keystone-api-types = { version = "0.1", features = ["openapi", "validate"], path = "../api-types/"} +openstack-keystone-api-types = { version = "0.1", features = ["openapi", "validate", "conv"], path = "../api-types/"} openstack-keystone-appcred-sql = { version = "0.1", path = "../appcred-sql/" } openstack-keystone-assignment-sql = { version = "0.1", path = "../assignment-sql/" } openstack-keystone-catalog-sql = { version = "0.1", path = "../catalog-sql/" } openstack-keystone-config = { version = "0.1", path = "../config" } -openstack-keystone-core = { version = "0.1", features = ["api"], path = "../core" } +openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } openstack-keystone-distributed-storage = { version = "0.1", path = "../storage/"} openstack-keystone-federation-sql = { version = "0.1", path = "../federation-sql" } openstack-keystone-k8s-auth-sql = { version = "0.1", path = "../k8s-auth-sql/" } diff --git a/crates/keystone/src/api/common.rs b/crates/keystone/src/api/common.rs index 99b9ca5e..cdd43aae 100644 --- a/crates/keystone/src/api/common.rs +++ b/crates/keystone/src/api/common.rs @@ -17,16 +17,14 @@ use url::Url; use openstack_keystone_api_types::Link; use openstack_keystone_config::Config; +use openstack_keystone_core_types::resource::{Domain, Project}; +use openstack_keystone_core_types::scope::Scope as ProviderScope; use crate::api::KeystoneApiError; use crate::api::types::ScopeProject; use crate::auth::AuthzInfo; -use crate::common::types::Scope as ProviderScope; use crate::keystone::ServiceState; -use crate::resource::{ - ResourceApi, - types::{Domain, Project}, -}; +use crate::resource::ResourceApi; /// Get the domain by ID or Name. /// @@ -225,11 +223,12 @@ mod tests { use rstest::rstest; use openstack_keystone_config::Config; + use openstack_keystone_core_types::resource::Domain; use super::*; use crate::api::tests::get_mocked_state; use crate::provider::Provider; - use crate::resource::{MockResourceProvider, types::Domain}; + use crate::resource::MockResourceProvider; #[tokio::test] async fn test_get_domain() { diff --git a/crates/keystone/src/api/error.rs b/crates/keystone/src/api/error.rs index 3d1a4ef5..3610fb46 100644 --- a/crates/keystone/src/api/error.rs +++ b/crates/keystone/src/api/error.rs @@ -13,4 +13,4 @@ // SPDX-License-Identifier: Apache-2.0 //! # Keystone API error. -pub use openstack_keystone_core::api::KeystoneApiError; +pub use openstack_keystone_api_types::error::KeystoneApiError; diff --git a/crates/keystone/src/api/mod.rs b/crates/keystone/src/api/mod.rs index da5fe23a..9a25e70c 100644 --- a/crates/keystone/src/api/mod.rs +++ b/crates/keystone/src/api/mod.rs @@ -128,8 +128,8 @@ pub(crate) mod tests { use std::sync::Arc; use openstack_keystone_config::Config; + use openstack_keystone_core_types::identity::UserResponseBuilder; - use crate::identity::types::UserResponseBuilder; use crate::keystone::{Service, ServiceState}; use crate::policy::{MockPolicy, PolicyError, PolicyEvaluationResult}; use crate::provider::ProviderBuilder; diff --git a/crates/keystone/src/api/types.rs b/crates/keystone/src/api/types.rs index 1a2b0940..edc02ca9 100644 --- a/crates/keystone/src/api/types.rs +++ b/crates/keystone/src/api/types.rs @@ -16,119 +16,3 @@ pub use openstack_keystone_api_types::Link; pub use openstack_keystone_api_types::catalog::*; pub use openstack_keystone_api_types::scope::*; pub use openstack_keystone_api_types::version::*; - -//use crate::catalog::types::Endpoint as ProviderEndpoint; -//use crate::common::types as provider_types; -//use crate::resource::types as resource_provider_types; - -//impl From<(Service, Vec)> for CatalogService { -// fn from(value: (Service, Vec)) -> Self { -// Self { -// id: value.0.id.clone(), -// name: value.0.name.clone(), -// r#type: value.0.r#type, -// endpoints: value.1.into_iter().map(Into::into).collect(), -// } -// } -//} - -//impl From for Endpoint { -// fn from(value: ProviderEndpoint) -> Self { -// Self { -// id: value.id.clone(), -// interface: value.interface.clone(), -// url: value.url.clone(), -// region: value.region_id.clone(), -// region_id: value.region_id.clone(), -// } -// } -//} - -//impl From)>> for Catalog { -// fn from(value: Vec<(Service, Vec)>) -> Self { -// Self( -// value -// .into_iter() -// .map(|(srv, eps)| (srv, eps).into()) -// .collect(), -// ) -// } -//} - -//impl From for Domain { -// fn from(value: resource_provider_types::Domain) -> Self { -// Self { -// id: Some(value.id), -// name: Some(value.name), -// } -// } -//} -// -//impl From<&resource_provider_types::Domain> for Domain { -// fn from(value: &resource_provider_types::Domain) -> Self { -// Self { -// id: Some(value.id.clone()), -// name: Some(value.name.clone()), -// } -// } -//} -// -//impl From for provider_types::Domain { -// fn from(value: Domain) -> Self { -// Self { -// id: value.id, -// name: value.name, -// } -// } -//} -// -//impl From for Domain { -// fn from(value: provider_types::Domain) -> Self { -// Self { -// id: value.id, -// name: value.name, -// } -// } -//} -// -//impl From for provider_types::Project { -// fn from(value: ScopeProject) -> Self { -// Self { -// id: value.id, -// name: value.name, -// domain: value.domain.map(Into::into), -// } -// } -//} -// -//impl From for ScopeProject { -// fn from(value: provider_types::Project) -> Self { -// Self { -// id: value.id, -// name: value.name, -// domain: value.domain.map(Into::into), -// } -// } -//} -// -//impl From<&provider_types::Project> for ScopeProject { -// fn from(value: &provider_types::Project) -> Self { -// Self::from(value.clone()) -// } -//} -// -//impl From for provider_types::System { -// fn from(value: System) -> Self { -// Self { all: value.all } -// } -//} -// -//impl From for provider_types::Scope { -// fn from(value: Scope) -> Self { -// match value { -// Scope::Project(scope) => Self::Project(scope.into()), -// Scope::Domain(scope) => Self::Domain(scope.into()), -// Scope::System(scope) => Self::System(scope.into()), -// } -// } -//} diff --git a/crates/keystone/src/api/v3/auth/project/list.rs b/crates/keystone/src/api/v3/auth/project/list.rs index 393f4d25..da37eeb1 100644 --- a/crates/keystone/src/api/v3/auth/project/list.rs +++ b/crates/keystone/src/api/v3/auth/project/list.rs @@ -17,14 +17,14 @@ use axum::{Json, extract::State, http::StatusCode, response::IntoResponse}; use serde_json::Value; use std::collections::HashSet; +use openstack_keystone_core_types::assignment::{AssignmentType, RoleAssignmentListParameters}; +use openstack_keystone_core_types::resource::ProjectListParameters; + use crate::api::v3::project::types::ProjectShortList; use crate::api::{auth::Auth, error::KeystoneApiError}; -use crate::assignment::{ - AssignmentApi, - types::{AssignmentType, RoleAssignmentListParameters}, -}; +use crate::assignment::AssignmentApi; use crate::keystone::ServiceState; -use crate::resource::{ResourceApi, types::ProjectListParameters}; +use crate::resource::ResourceApi; /// Get available project scopes. /// @@ -110,14 +110,16 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::assignment::*; + use openstack_keystone_core_types::resource::{ + Project as ProviderProject, ProjectListParameters, + }; + use crate::api::tests::get_mocked_state; use crate::api::v3::project::types::ProjectShort; - use crate::assignment::{MockAssignmentProvider, types::*}; + use crate::assignment::MockAssignmentProvider; use crate::provider::Provider; - use crate::resource::{ - MockResourceProvider, - types::{Project as ProviderProject, ProjectListParameters}, - }; + use crate::resource::MockResourceProvider; use super::super::openapi_router; use super::*; diff --git a/crates/keystone/src/api/v3/auth/token/common.rs b/crates/keystone/src/api/v3/auth/token/common.rs index 94b7238e..005b301a 100644 --- a/crates/keystone/src/api/v3/auth/token/common.rs +++ b/crates/keystone/src/api/v3/auth/token/common.rs @@ -120,16 +120,14 @@ pub(super) async fn get_authz_info( #[cfg(test)] mod tests { + use openstack_keystone_core_types::identity::{UserPasswordAuthRequest, UserResponseBuilder}; use super::super::types::*; use super::*; use crate::api::KeystoneApiError; use crate::api::tests::get_mocked_state; use crate::auth::AuthenticatedInfo; - use crate::identity::{ - MockIdentityProvider, - types::{UserPasswordAuthRequest, UserResponseBuilder}, - }; + use crate::identity::MockIdentityProvider; use crate::provider::Provider; use crate::token::MockTokenProvider; diff --git a/crates/keystone/src/api/v3/auth/token/create.rs b/crates/keystone/src/api/v3/auth/token/create.rs index f0ab032e..15d63dcf 100644 --- a/crates/keystone/src/api/v3/auth/token/create.rs +++ b/crates/keystone/src/api/v3/auth/token/create.rs @@ -21,6 +21,8 @@ use axum::{ }; use validator::Validate; +use openstack_keystone_core::api::v3::auth::token::token_impl::build_api_token_v3; + use crate::api::v3::auth::token::common::{authenticate_request, get_authz_info}; use crate::api::v3::auth::token::types::{AuthRequest, CreateTokenParameters, TokenResponse}; use crate::api::{Catalog, CatalogService, error::KeystoneApiError}; @@ -75,7 +77,7 @@ pub(super) async fn create( .await?; let mut api_token = TokenResponse { - token: token.build_api_token_v3(&state).await?, + token: build_api_token_v3(&token, &state).await?, }; if !query.nocatalog.is_some_and(|x| x) { let catalog: Catalog = Catalog( @@ -121,23 +123,20 @@ mod tests { use tracing_test::traced_test; use openstack_keystone_config::Config; + use openstack_keystone_core_types::identity::{UserPasswordAuthRequest, UserResponseBuilder}; + use openstack_keystone_core_types::resource::{Domain, Project}; + use openstack_keystone_core_types::token::{ProjectScopePayload, Token as ProviderToken}; use crate::api::v3::auth::token::types::*; use crate::assignment::MockAssignmentProvider; use crate::auth::AuthenticatedInfo; use crate::catalog::MockCatalogProvider; - use crate::identity::{ - MockIdentityProvider, - types::{UserPasswordAuthRequest, UserResponseBuilder}, - }; + use crate::identity::MockIdentityProvider; use crate::keystone::Service; use crate::policy::MockPolicy; use crate::provider::Provider; - use crate::resource::{ - MockResourceProvider, - types::{Domain, Project}, - }; - use crate::token::{MockTokenProvider, ProjectScopePayload, Token as ProviderToken}; + use crate::resource::MockResourceProvider; + use crate::token::MockTokenProvider; use super::super::openapi_router; diff --git a/crates/keystone/src/api/v3/auth/token/show.rs b/crates/keystone/src/api/v3/auth/token/show.rs index 032fa096..7d92dcf4 100644 --- a/crates/keystone/src/api/v3/auth/token/show.rs +++ b/crates/keystone/src/api/v3/auth/token/show.rs @@ -31,6 +31,8 @@ use axum::{ use serde_json::{json, to_value}; use tracing::error; +use openstack_keystone_core::api::v3::auth::token::token_impl::build_api_token_v3; + use crate::api::v3::auth::token::types::{TokenResponse, ValidateTokenParameters}; use crate::api::{Catalog, CatalogService, auth::Auth, error::KeystoneApiError}; use crate::catalog::CatalogApi; @@ -97,7 +99,7 @@ pub(super) async fn show( .await?; //// Expand the token since we didn't expand it before. - let mut response_token = token.build_api_token_v3(&state).await?; + let mut response_token = build_api_token_v3(&token, &state).await?; if !query.nocatalog.is_some_and(|x| x) { let catalog: Catalog = Catalog( @@ -138,13 +140,16 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::identity::UserResponseBuilder; + use openstack_keystone_core_types::resource::Domain; + use super::super::openapi_router; use crate::api::tests::get_mocked_state; use crate::api::v3::auth::token::types::*; use crate::catalog::MockCatalogProvider; - use crate::identity::{MockIdentityProvider, types::UserResponseBuilder}; + use crate::identity::MockIdentityProvider; use crate::provider::Provider; - use crate::resource::{MockResourceProvider, types::Domain}; + use crate::resource::MockResourceProvider; use crate::token::{ MockTokenProvider, Token as ProviderToken, TokenProviderError, UnscopedPayload, }; diff --git a/crates/keystone/src/api/v3/group/mod.rs b/crates/keystone/src/api/v3/group/mod.rs index 508f288f..0a6c0304 100644 --- a/crates/keystone/src/api/v3/group/mod.rs +++ b/crates/keystone/src/api/v3/group/mod.rs @@ -81,17 +81,25 @@ async fn show( Path(group_id): Path, State(state): State, ) -> Result { - state - .provider - .get_identity_provider() - .get_group(&state, &group_id) - .await - .map(|x| { - x.ok_or_else(|| KeystoneApiError::NotFound { - resource: "group".into(), - identifier: group_id, - }) - })? + Ok(( + StatusCode::OK, + Json(GroupResponse { + group: Group::from( + state + .provider + .get_identity_provider() + .get_group(&state, &group_id) + .await + .map(|x| { + x.ok_or_else(|| KeystoneApiError::NotFound { + resource: "group".into(), + identifier: group_id, + }) + })??, + ), + }), + ) + .into_response()) } /// Create group @@ -116,7 +124,13 @@ async fn create( .get_identity_provider() .create_group(&state, req.into()) .await?; - Ok((StatusCode::CREATED, res).into_response()) + Ok(( + StatusCode::CREATED, + Json(GroupResponse { + group: Group::from(res), + }), + ) + .into_response()) } /// Delete group @@ -158,11 +172,7 @@ mod tests { use super::openapi_router; use crate::api::tests::get_mocked_state; - use crate::identity::{ - MockIdentityProvider, - error::IdentityProviderError, - types::{Group, GroupCreate, GroupListParameters}, - }; + use crate::identity::{MockIdentityProvider, error::IdentityProviderError}; use crate::{ api::v3::group::types::{ Group as ApiGroup, GroupCreate as ApiGroupCreate, GroupCreateRequest, GroupList, @@ -170,6 +180,7 @@ mod tests { }, provider::Provider, }; + use openstack_keystone_core_types::identity::*; #[tokio::test] async fn test_list() { diff --git a/crates/keystone/src/api/v3/project/create.rs b/crates/keystone/src/api/v3/project/create.rs index 33983f30..e9685fbd 100644 --- a/crates/keystone/src/api/v3/project/create.rs +++ b/crates/keystone/src/api/v3/project/create.rs @@ -87,11 +87,13 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::resource::Project as ProviderProject; + use super::super::openapi_router; use crate::api::tests::get_mocked_state; use crate::api::v3::project::types::*; use crate::provider::Provider; - use crate::resource::{MockResourceProvider, types::Project as ProviderProject}; + use crate::resource::MockResourceProvider; #[traced_test] #[tokio::test] diff --git a/crates/keystone/src/api/v3/project/delete.rs b/crates/keystone/src/api/v3/project/delete.rs index e05c68b0..c1ed688c 100644 --- a/crates/keystone/src/api/v3/project/delete.rs +++ b/crates/keystone/src/api/v3/project/delete.rs @@ -71,10 +71,12 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::resource as provider_types; + use super::super::openapi_router; use crate::api::tests::get_mocked_state; use crate::provider::Provider; - use crate::resource::{MockResourceProvider, types as provider_types}; + use crate::resource::MockResourceProvider; #[tokio::test] #[traced_test] diff --git a/crates/keystone/src/api/v3/role/create.rs b/crates/keystone/src/api/v3/role/create.rs index f4484243..5e882670 100644 --- a/crates/keystone/src/api/v3/role/create.rs +++ b/crates/keystone/src/api/v3/role/create.rs @@ -75,14 +75,13 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::role::{RoleBuilder, RoleCreate}; + use super::super::openapi_router; use crate::api::tests::get_mocked_state; use crate::api::v3::role::types::{Role as ApiRole, RoleResponse}; use crate::provider::Provider; - use crate::role::{ - MockRoleProvider, - types::{RoleBuilder, RoleCreate}, - }; + use crate::role::MockRoleProvider; #[tokio::test] async fn test_create() { diff --git a/crates/keystone/src/api/v3/role/list.rs b/crates/keystone/src/api/v3/role/list.rs index 7e4a30bb..2e26b29e 100644 --- a/crates/keystone/src/api/v3/role/list.rs +++ b/crates/keystone/src/api/v3/role/list.rs @@ -61,23 +61,17 @@ mod tests { http::{Request, StatusCode}, }; use http_body_util::BodyExt; // for `collect` - use serde_json::json; - use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::role::{RoleBuilder, RoleListParameters}; + use super::super::openapi_router; use crate::api::tests::get_mocked_state; - use crate::api::v3::role::types::{ - Role as ApiRole, //GroupCreate as ApiGroupCreate, GroupCreateRequest, - RoleList, - }; + use crate::api::v3::role::types::{Role as ApiRole, RoleList}; use crate::provider::Provider; - use crate::role::{ - MockRoleProvider, - types::{RoleBuilder, RoleListParameters}, - }; + use crate::role::MockRoleProvider; #[tokio::test] async fn test_list() { diff --git a/crates/keystone/src/api/v3/role/show.rs b/crates/keystone/src/api/v3/role/show.rs index 389d8cdc..0cf8f6d5 100644 --- a/crates/keystone/src/api/v3/role/show.rs +++ b/crates/keystone/src/api/v3/role/show.rs @@ -13,11 +13,14 @@ // SPDX-License-Identifier: Apache-2.0 use axum::{ + Json, extract::{Path, State}, + http::StatusCode, response::IntoResponse, }; -use super::types::RoleResponse; +use openstack_keystone_api_types::v3::role::{Role, RoleResponse}; + use crate::api::auth::Auth; use crate::api::error::KeystoneApiError; use crate::keystone::ServiceState; @@ -41,17 +44,25 @@ pub(super) async fn show( Path(role_id): Path, State(state): State, ) -> Result { - state - .provider - .get_role_provider() - .get_role(&state, &role_id) - .await - .map(|x| { - x.ok_or_else(|| KeystoneApiError::NotFound { - resource: "role".into(), - identifier: role_id, - }) - })? + Ok(( + StatusCode::OK, + Json(RoleResponse { + role: Role::from( + state + .provider + .get_role_provider() + .get_role(&state, &role_id) + .await + .map(|x| { + x.ok_or_else(|| KeystoneApiError::NotFound { + resource: "role".into(), + identifier: role_id, + }) + })??, + ), + }), + ) + .into_response()) } #[cfg(test)] @@ -65,11 +76,13 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::role::RoleBuilder; + use super::super::openapi_router; use crate::api::tests::get_mocked_state; use crate::api::v3::role::types::{Role as ApiRole, RoleResponse}; use crate::provider::Provider; - use crate::role::{MockRoleProvider, types::RoleBuilder}; + use crate::role::MockRoleProvider; #[tokio::test] async fn test_get() { diff --git a/crates/keystone/src/api/v3/role_assignment/list.rs b/crates/keystone/src/api/v3/role_assignment/list.rs index aa379393..ce608da6 100644 --- a/crates/keystone/src/api/v3/role_assignment/list.rs +++ b/crates/keystone/src/api/v3/role_assignment/list.rs @@ -76,16 +76,17 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::assignment::{ + Assignment, AssignmentType, RoleAssignmentListParameters, + }; + use super::super::openapi_router; use crate::api::tests::get_mocked_state; use crate::api::v3::role_assignment::types::{ Assignment as ApiAssignment, AssignmentList as ApiAssignmentList, Project, Role, Scope, User, }; - use crate::assignment::{ - MockAssignmentProvider, - types::{Assignment, AssignmentType, RoleAssignmentListParameters}, - }; + use crate::assignment::MockAssignmentProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/api/v3/role_assignment/project/user/role/check.rs b/crates/keystone/src/api/v3/role_assignment/project/user/role/check.rs index 4d74c83b..723e4f90 100644 --- a/crates/keystone/src/api/v3/role_assignment/project/user/role/check.rs +++ b/crates/keystone/src/api/v3/role_assignment/project/user/role/check.rs @@ -21,13 +21,13 @@ use axum::{ use serde_json::json; use tracing::info; +use openstack_keystone_core_types::assignment::Assignment; +use openstack_keystone_core_types::assignment::RoleAssignmentListParameters; + use crate::api::error::KeystoneApiError; use crate::keystone::ServiceState; use crate::{ - api::auth::Auth, - assignment::{AssignmentApi, types::RoleAssignmentListParameters}, - identity::IdentityApi, - resource::ResourceApi, + api::auth::Auth, assignment::AssignmentApi, identity::IdentityApi, resource::ResourceApi, role::RoleApi, }; @@ -120,7 +120,7 @@ pub(super) async fn check( ) .await?; - let grants: Vec = assignments?.into_iter().collect(); + let grants: Vec = assignments?.into_iter().collect(); if grants.into_iter().any(|x| x.role_id == role_id) { Ok(StatusCode::NO_CONTENT.into_response()) @@ -142,13 +142,18 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::assignment::*; + use openstack_keystone_core_types::identity::*; + use openstack_keystone_core_types::resource::*; + use openstack_keystone_core_types::role::*; + use crate::api::tests::get_mocked_state; use crate::api::v3::role_assignment::openapi_router; - use crate::assignment::{MockAssignmentProvider, types::*}; - use crate::identity::{MockIdentityProvider, types::*}; + use crate::assignment::MockAssignmentProvider; + use crate::identity::MockIdentityProvider; use crate::provider::Provider; - use crate::resource::{MockResourceProvider, types::Project}; - use crate::role::{MockRoleProvider, types::*}; + use crate::resource::MockResourceProvider; + use crate::role::MockRoleProvider; #[tokio::test] #[traced_test] diff --git a/crates/keystone/src/api/v3/role_assignment/project/user/role/grant.rs b/crates/keystone/src/api/v3/role_assignment/project/user/role/grant.rs index f1dc39b5..40d51f47 100644 --- a/crates/keystone/src/api/v3/role_assignment/project/user/role/grant.rs +++ b/crates/keystone/src/api/v3/role_assignment/project/user/role/grant.rs @@ -21,13 +21,12 @@ use axum::{ use serde_json::json; use tracing::info; +use openstack_keystone_core_types::assignment::AssignmentCreate; + use crate::api::error::KeystoneApiError; use crate::keystone::ServiceState; use crate::{ - api::auth::Auth, - assignment::{AssignmentApi, types::AssignmentCreate}, - identity::IdentityApi, - resource::ResourceApi, + api::auth::Auth, assignment::AssignmentApi, identity::IdentityApi, resource::ResourceApi, role::RoleApi, }; @@ -131,13 +130,18 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::assignment::*; + use openstack_keystone_core_types::identity::*; + use openstack_keystone_core_types::resource::*; + use openstack_keystone_core_types::role::*; + use crate::api::tests::get_mocked_state; use crate::api::v3::role_assignment::openapi_router; - use crate::assignment::{MockAssignmentProvider, types::*}; - use crate::identity::{MockIdentityProvider, types::*}; + use crate::assignment::MockAssignmentProvider; + use crate::identity::MockIdentityProvider; use crate::provider::Provider; - use crate::resource::{MockResourceProvider, types::Project}; - use crate::role::{MockRoleProvider, types::*}; + use crate::resource::MockResourceProvider; + use crate::role::MockRoleProvider; #[tokio::test] #[traced_test] diff --git a/crates/keystone/src/api/v3/role_assignment/project/user/role/revoke.rs b/crates/keystone/src/api/v3/role_assignment/project/user/role/revoke.rs index 65bc4f12..b8156d97 100644 --- a/crates/keystone/src/api/v3/role_assignment/project/user/role/revoke.rs +++ b/crates/keystone/src/api/v3/role_assignment/project/user/role/revoke.rs @@ -25,12 +25,10 @@ use tracing::info; use crate::api::error::KeystoneApiError; use crate::keystone::ServiceState; use crate::{ - api::auth::Auth, - assignment::{AssignmentApi, types::AssignmentBuilder, types::AssignmentType}, - identity::IdentityApi, - resource::ResourceApi, + api::auth::Auth, assignment::AssignmentApi, identity::IdentityApi, resource::ResourceApi, role::RoleApi, }; +use openstack_keystone_core_types::assignment::{AssignmentBuilder, AssignmentType}; /// Revoke role from user on project /// @@ -143,13 +141,17 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::identity::*; + use openstack_keystone_core_types::resource::*; + use openstack_keystone_core_types::role::*; + use crate::api::tests::get_mocked_state; use crate::api::v3::role_assignment::openapi_router; use crate::assignment::MockAssignmentProvider; - use crate::identity::{MockIdentityProvider, types::*}; + use crate::identity::MockIdentityProvider; use crate::provider::Provider; - use crate::resource::{MockResourceProvider, types::Project}; - use crate::role::{MockRoleProvider, types::*}; + use crate::resource::MockResourceProvider; + use crate::role::MockRoleProvider; #[tokio::test] async fn test_revoke_success() { diff --git a/crates/keystone/src/api/v3/user/mod.rs b/crates/keystone/src/api/v3/user/mod.rs index 458c1d39..60cf0180 100644 --- a/crates/keystone/src/api/v3/user/mod.rs +++ b/crates/keystone/src/api/v3/user/mod.rs @@ -84,17 +84,25 @@ async fn show( Path(user_id): Path, State(state): State, ) -> Result { - state - .provider - .get_identity_provider() - .get_user(&state, &user_id) - .await - .map(|x| { - x.ok_or_else(|| KeystoneApiError::NotFound { - resource: "user".into(), - identifier: user_id, - }) - })? + Ok(( + StatusCode::OK, + Json(UserResponse { + user: User::from( + state + .provider + .get_identity_provider() + .get_user(&state, &user_id) + .await + .map(|x| { + x.ok_or_else(|| KeystoneApiError::NotFound { + resource: "user".into(), + identifier: user_id, + }) + })??, + ), + }), + ) + .into_response()) } /// Create user @@ -119,7 +127,13 @@ async fn create( .get_identity_provider() .create_user(&state, req.into()) .await?; - Ok((StatusCode::CREATED, user).into_response()) + Ok(( + StatusCode::CREATED, + Json(UserResponse { + user: User::from(user), + }), + ) + .into_response()) } /// Delete user @@ -187,17 +201,17 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::identity::{ + Group, UserCreate, UserListParameters, UserResponseBuilder, + }; + use super::openapi_router; use crate::api::tests::get_mocked_state; use crate::api::v3::user::types::{ UserBuilder as ApiUser, UserCreateBuilder as ApiUserCreate, UserCreateRequest, UserList, UserResponse as ApiUserResponse, }; - use crate::identity::{ - MockIdentityProvider, - error::IdentityProviderError, - types::{Group, UserCreate, UserListParameters, UserResponseBuilder}, - }; + use crate::identity::{MockIdentityProvider, error::IdentityProviderError}; use crate::{ api::v3::group::types::{Group as ApiGroup, GroupList}, provider::Provider, diff --git a/crates/keystone/src/api/v4/group/mod.rs b/crates/keystone/src/api/v4/group/mod.rs index fea04388..b51fdc23 100644 --- a/crates/keystone/src/api/v4/group/mod.rs +++ b/crates/keystone/src/api/v4/group/mod.rs @@ -33,17 +33,15 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::identity::{Group, GroupCreate, GroupListParameters}; + use super::openapi_router; use crate::api::tests::get_mocked_state; use crate::api::v3::group::types::{ Group as ApiGroup, GroupCreate as ApiGroupCreate, GroupCreateRequest, GroupList, GroupResponse, }; - use crate::identity::{ - MockIdentityProvider, - error::IdentityProviderError, - types::{Group, GroupCreate, GroupListParameters}, - }; + use crate::identity::{MockIdentityProvider, error::IdentityProviderError}; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/api/v4/token/restriction.rs b/crates/keystone/src/api/v4/token/restriction.rs index e5101a11..f23f4a13 100644 --- a/crates/keystone/src/api/v4/token/restriction.rs +++ b/crates/keystone/src/api/v4/token/restriction.rs @@ -56,7 +56,8 @@ pub(super) fn openapi_router() -> OpenApiRouter { #[cfg(test)] mod tests { - use crate::identity::types::*; + use openstack_keystone_core_types::identity::*; + use crate::token::{MockTokenProvider, Token, UnscopedPayload}; pub(crate) fn get_token_provider_mock_with_mocks() -> MockTokenProvider { diff --git a/crates/keystone/src/api/v4/token/restriction/create.rs b/crates/keystone/src/api/v4/token/restriction/create.rs index b075f3b9..abe1cbbc 100644 --- a/crates/keystone/src/api/v4/token/restriction/create.rs +++ b/crates/keystone/src/api/v4/token/restriction/create.rs @@ -66,7 +66,13 @@ pub(super) async fn create( .get_token_provider() .create_token_restriction(&state, req.into()) .await?; - Ok((StatusCode::CREATED, res).into_response()) + Ok(( + StatusCode::CREATED, + Json(TokenRestrictionResponse { + restriction: TokenRestriction::from(res), + }), + ) + .into_response()) } #[cfg(test)] @@ -79,14 +85,15 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::role::RoleRef as ProviderRoleRef; + use openstack_keystone_core_types::token as provider_types; + use super::{ super::{openapi_router, tests::get_token_provider_mock_with_mocks}, *, }; use crate::api::tests::get_mocked_state; use crate::provider::Provider; - use crate::role::types::RoleRef as ProviderRoleRef; - use crate::token::types as provider_types; #[tokio::test] async fn test_create() { diff --git a/crates/keystone/src/api/v4/token/restriction/delete.rs b/crates/keystone/src/api/v4/token/restriction/delete.rs index 18016abc..f5a5143a 100644 --- a/crates/keystone/src/api/v4/token/restriction/delete.rs +++ b/crates/keystone/src/api/v4/token/restriction/delete.rs @@ -93,11 +93,13 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::role::RoleRef as ProviderRoleRef; + use openstack_keystone_core_types::token as provider_types; + use super::super::{openapi_router, tests::get_token_provider_mock_with_mocks}; use crate::api::tests::get_mocked_state; use crate::provider::Provider; - use crate::role::types::RoleRef as ProviderRoleRef; - use crate::token::{TokenProviderError, types as provider_types}; + use crate::token::TokenProviderError; #[tokio::test] async fn test_delete() { diff --git a/crates/keystone/src/api/v4/token/restriction/list.rs b/crates/keystone/src/api/v4/token/restriction/list.rs index baf0bd7f..242f1001 100644 --- a/crates/keystone/src/api/v4/token/restriction/list.rs +++ b/crates/keystone/src/api/v4/token/restriction/list.rs @@ -21,13 +21,13 @@ use axum::{ }; use serde_json::to_value; +use openstack_keystone_core_types::token::TokenRestrictionListParameters as ProviderTokenRestrictionListParameters; + use crate::api::auth::Auth; use crate::api::error::KeystoneApiError; use crate::api::v4::token::types::*; use crate::keystone::ServiceState; -use crate::token::{ - TokenApi, types::TokenRestrictionListParameters as ProviderTokenRestrictionListParameters, -}; +use crate::token::TokenApi; /// List token restrictions. /// @@ -96,6 +96,9 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::role::RoleRef as ProviderRoleRef; + use openstack_keystone_core_types::token as provider_types; + use super::{ super::{openapi_router, tests::get_token_provider_mock_with_mocks}, *, @@ -103,8 +106,6 @@ mod tests { use crate::api::tests::get_mocked_state; use crate::api::v3::role::types::RoleRef; use crate::provider::Provider; - use crate::role::types::RoleRef as ProviderRoleRef; - use crate::token::types as provider_types; #[tokio::test] async fn test_list() { diff --git a/crates/keystone/src/api/v4/token/restriction/show.rs b/crates/keystone/src/api/v4/token/restriction/show.rs index edc7e9a4..ada53802 100644 --- a/crates/keystone/src/api/v4/token/restriction/show.rs +++ b/crates/keystone/src/api/v4/token/restriction/show.rs @@ -14,7 +14,9 @@ //! Show token restriction. use axum::{ + Json, extract::{Path, State}, + http::StatusCode, response::IntoResponse, }; @@ -73,7 +75,13 @@ pub(super) async fn show( None, ) .await?; - Ok(current) + Ok(( + StatusCode::OK, + Json(TokenRestrictionResponse { + restriction: TokenRestriction::from(current), + }), + ) + .into_response()) } #[cfg(test)] @@ -86,6 +94,9 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::role::RoleRef as ProviderRoleRef; + use openstack_keystone_core_types::token as provider_types; + use super::{ super::{openapi_router, tests::get_token_provider_mock_with_mocks}, *, @@ -93,8 +104,6 @@ mod tests { use crate::api::tests::get_mocked_state; use crate::api::v3::role::types::RoleRef; use crate::provider::Provider; - use crate::role::types::RoleRef as ProviderRoleRef; - use crate::token::types as provider_types; #[tokio::test] async fn test_get() { diff --git a/crates/keystone/src/api/v4/token/restriction/update.rs b/crates/keystone/src/api/v4/token/restriction/update.rs index 30a410dd..1fba1b58 100644 --- a/crates/keystone/src/api/v4/token/restriction/update.rs +++ b/crates/keystone/src/api/v4/token/restriction/update.rs @@ -16,6 +16,7 @@ use axum::{ Json, extract::{Path, State}, + http::StatusCode, response::IntoResponse, }; use validator::Validate; @@ -81,7 +82,13 @@ pub(super) async fn update( .get_token_provider() .update_token_restriction(&state, &id, req.into()) .await?; - Ok(res.into_response()) + Ok(( + StatusCode::OK, + Json(TokenRestrictionResponse { + restriction: TokenRestriction::from(res), + }), + ) + .into_response()) } #[cfg(test)] @@ -95,13 +102,14 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::token as provider_types; + use super::{ super::{openapi_router, tests::get_token_provider_mock_with_mocks}, *, }; use crate::api::tests::get_mocked_state; use crate::provider::Provider; - use crate::token::types as provider_types; #[tokio::test] #[traced_test] diff --git a/crates/keystone/src/api/v4/user/mod.rs b/crates/keystone/src/api/v4/user/mod.rs index adb9e3ab..41095887 100644 --- a/crates/keystone/src/api/v4/user/mod.rs +++ b/crates/keystone/src/api/v4/user/mod.rs @@ -82,17 +82,25 @@ async fn show( Path(user_id): Path, State(state): State, ) -> Result { - state - .provider - .get_identity_provider() - .get_user(&state, &user_id) - .await - .map(|x| { - x.ok_or_else(|| KeystoneApiError::NotFound { - resource: "user".into(), - identifier: user_id, - }) - })? + Ok(( + StatusCode::OK, + Json(UserResponse { + user: User::from( + state + .provider + .get_identity_provider() + .get_user(&state, &user_id) + .await + .map(|x| { + x.ok_or_else(|| KeystoneApiError::NotFound { + resource: "user".into(), + identifier: user_id, + }) + })??, + ), + }), + ) + .into_response()) } /// Create user @@ -117,7 +125,13 @@ async fn create( .get_identity_provider() .create_user(&state, req.into()) .await?; - Ok((StatusCode::CREATED, user).into_response()) + Ok(( + StatusCode::CREATED, + Json(UserResponse { + user: User::from(user), + }), + ) + .into_response()) } /// Delete user @@ -185,6 +199,8 @@ mod tests { use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; + use openstack_keystone_core_types::identity::*; + use super::openapi_router; use crate::api::tests::get_mocked_state; use crate::api::v3::group::types::{Group as ApiGroup, GroupList}; @@ -195,7 +211,7 @@ mod tests { use crate::identity::{ MockIdentityProvider, error::IdentityProviderError, - types::{Group, UserCreate, UserListParameters, UserResponseBuilder}, + // types::{Group, UserCreate, UserListParameters, UserResponseBuilder}, }; use crate::provider::Provider; diff --git a/crates/keystone/src/federation/api/auth.rs b/crates/keystone/src/federation/api/auth.rs index 0430eb51..f1bc5593 100644 --- a/crates/keystone/src/federation/api/auth.rs +++ b/crates/keystone/src/federation/api/auth.rs @@ -31,9 +31,11 @@ use openidconnect::{ }; use crate::api::error::KeystoneApiError; -use crate::federation::types::{AuthState, MappingListParameters as ProviderMappingListParameters}; use crate::federation::{FederationApi, api::error::OidcError, api::types::*}; use crate::keystone::ServiceState; +use openstack_keystone_core_types::federation::{ + AuthState, MappingListParameters as ProviderMappingListParameters, +}; pub(super) fn openapi_router() -> OpenApiRouter { OpenApiRouter::new().routes(routes!(post)) diff --git a/crates/keystone/src/federation/api/common.rs b/crates/keystone/src/federation/api/common.rs index b743482f..e88de775 100644 --- a/crates/keystone/src/federation/api/common.rs +++ b/crates/keystone/src/federation/api/common.rs @@ -17,14 +17,14 @@ use serde_json::Value; use openidconnect::IdTokenClaims; use openidconnect::core::CoreGenderClaim; +use openstack_keystone_core_types::federation::{ + IdentityProvider as ProviderIdentityProvider, Mapping as ProviderMapping, +}; + use crate::federation::api::{ error::OidcError, types::{AllOtherClaims, MappedUserData, MappedUserDataBuilder}, }; -use crate::federation::types::{ - identity_provider::IdentityProvider as ProviderIdentityProvider, - mapping::Mapping as ProviderMapping, -}; use crate::keystone::ServiceState; /// Validate bound claims in the token. diff --git a/crates/keystone/src/federation/api/identity_provider/create.rs b/crates/keystone/src/federation/api/identity_provider/create.rs index b9e9c35c..06ea4576 100644 --- a/crates/keystone/src/federation/api/identity_provider/create.rs +++ b/crates/keystone/src/federation/api/identity_provider/create.rs @@ -65,7 +65,13 @@ pub(super) async fn create( .get_federation_provider() .create_identity_provider(&state, req.into()) .await?; - Ok((StatusCode::CREATED, res).into_response()) + Ok(( + StatusCode::CREATED, + Json(IdentityProviderResponse { + identity_provider: IdentityProvider::from(res), + }), + ) + .into_response()) } #[cfg(test)] @@ -75,14 +81,15 @@ mod tests { http::{Request, StatusCode, header}, }; use http_body_util::BodyExt; // for `collect` - use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::federation as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::federation::{MockFederationProvider, types as provider_types}; + use crate::federation::MockFederationProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/federation/api/identity_provider/delete.rs b/crates/keystone/src/federation/api/identity_provider/delete.rs index fb43e011..47e02822 100644 --- a/crates/keystone/src/federation/api/identity_provider/delete.rs +++ b/crates/keystone/src/federation/api/identity_provider/delete.rs @@ -95,17 +95,15 @@ mod tests { body::Body, http::{Request, StatusCode}, }; - // for `collect` - use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::federation as provider_types; + use super::super::openapi_router; use crate::api::tests::get_mocked_state; - use crate::federation::{ - MockFederationProvider, error::FederationProviderError, types as provider_types, - }; + use crate::federation::{MockFederationProvider, error::FederationProviderError}; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/federation/api/identity_provider/list.rs b/crates/keystone/src/federation/api/identity_provider/list.rs index 9e27f7ed..5d80fe0e 100644 --- a/crates/keystone/src/federation/api/identity_provider/list.rs +++ b/crates/keystone/src/federation/api/identity_provider/list.rs @@ -23,11 +23,11 @@ use serde_json::to_value; use std::collections::HashSet; use validator::Validate; +use openstack_keystone_api_types::federation::*; +use openstack_keystone_core_types::federation::IdentityProviderListParameters as ProviderIdentityProviderListParameters; + use crate::api::{KeystoneApiError, auth::Auth, common::build_pagination_links}; -use crate::federation::{ - FederationApi, api::types::*, - types::IdentityProviderListParameters as ProviderIdentityProviderListParameters, -}; +use crate::federation::FederationApi; use crate::keystone::ServiceState; /// List identity providers. @@ -118,21 +118,22 @@ pub(super) async fn list( #[cfg(test)] mod tests { + use std::collections::HashSet; + use axum::{ body::Body, http::{Request, StatusCode}, }; use http_body_util::BodyExt; // for `collect` - - use std::collections::HashSet; - use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::federation as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::federation::{MockFederationProvider, types as provider_types}; + use crate::federation::MockFederationProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/federation/api/identity_provider/show.rs b/crates/keystone/src/federation/api/identity_provider/show.rs index f1a3e98c..4e6f3879 100644 --- a/crates/keystone/src/federation/api/identity_provider/show.rs +++ b/crates/keystone/src/federation/api/identity_provider/show.rs @@ -14,7 +14,9 @@ //! Identity providers: show IDP. use axum::{ + Json, extract::{Path, State}, + http::StatusCode, response::IntoResponse, }; @@ -72,7 +74,13 @@ pub(super) async fn show( None, ) .await?; - Ok(current) + Ok(( + StatusCode::OK, + Json(IdentityProviderResponse { + identity_provider: IdentityProvider::from(current), + }), + ) + .into_response()) } #[cfg(test)] @@ -82,14 +90,15 @@ mod tests { http::{Request, StatusCode}, }; use http_body_util::BodyExt; // for `collect` - use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::federation as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::federation::{MockFederationProvider, types as provider_types}; + use crate::federation::MockFederationProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/federation/api/identity_provider/update.rs b/crates/keystone/src/federation/api/identity_provider/update.rs index 9eaeede5..5fcde80c 100644 --- a/crates/keystone/src/federation/api/identity_provider/update.rs +++ b/crates/keystone/src/federation/api/identity_provider/update.rs @@ -16,6 +16,7 @@ use axum::{ Json, extract::{Path, State}, + http::StatusCode, response::IntoResponse, }; use validator::Validate; @@ -77,7 +78,13 @@ pub(super) async fn update( .get_federation_provider() .update_identity_provider(&state, &idp_id, req.into()) .await?; - Ok(res.into_response()) + Ok(( + StatusCode::OK, + Json(IdentityProviderResponse { + identity_provider: IdentityProvider::from(res), + }), + ) + .into_response()) } #[cfg(test)] @@ -87,14 +94,15 @@ mod tests { http::{Request, StatusCode, header}, }; use http_body_util::BodyExt; // for `collect` - use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::federation as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::federation::{MockFederationProvider, types as provider_types}; + use crate::federation::MockFederationProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/federation/api/jwt.rs b/crates/keystone/src/federation/api/jwt.rs index 42c37c81..b75527e7 100644 --- a/crates/keystone/src/federation/api/jwt.rs +++ b/crates/keystone/src/federation/api/jwt.rs @@ -33,6 +33,8 @@ use openidconnect::core::{ use openidconnect::reqwest; use openidconnect::{Client, ClientId, IdToken, IssuerUrl, JsonWebKeySet, JsonWebKeySetUrl, Nonce}; +use openstack_keystone_core::api::v4::auth::token::token_impl::build_api_token_v4; + use super::error::OidcError; use crate::api::v4::auth::token::types::TokenResponse as KeystoneTokenResponse; use crate::api::{ @@ -42,23 +44,20 @@ use crate::api::{ }; use crate::auth::{AuthenticatedInfo, AuthenticationError}; use crate::catalog::CatalogApi; -use crate::common::types as provider_types; -use crate::federation::{ - FederationApi, - api::types::*, - types::{ - MappingListParameters as ProviderMappingListParameters, - MappingType as ProviderMappingType, - //Project as ProviderProject, Scope as ProviderScope, - }, -}; -use crate::identity::{ - IdentityApi, - error::IdentityProviderError, - types::{FederationBuilder, FederationProtocol, UserCreateBuilder}, -}; +//use crate::common::types as provider_types; +use crate::federation::{FederationApi, api::types::*}; +use crate::identity::{IdentityApi, error::IdentityProviderError}; use crate::keystone::ServiceState; use crate::token::TokenApi; +use openstack_keystone_core_types::federation::{ + MappingListParameters as ProviderMappingListParameters, + MappingType as ProviderMappingType, + //Project as ProviderProject, Scope as ProviderScope, +}; +use openstack_keystone_core_types::identity::{ + FederationBuilder, FederationProtocol, UserCreateBuilder, +}; +use openstack_keystone_core_types::scope as provider_types; use super::common::{map_user_data, validate_bound_claims}; @@ -339,7 +338,7 @@ pub async fn login( .map_err(KeystoneApiError::forbidden)?; let mut api_token = KeystoneTokenResponse { - token: token.build_api_token_v4(&state).await?, + token: build_api_token_v4(&token, &state).await?, }; let catalog: Catalog = Catalog( state diff --git a/crates/keystone/src/federation/api/mapping/create.rs b/crates/keystone/src/federation/api/mapping/create.rs index c7afd0a6..b5df6a5c 100644 --- a/crates/keystone/src/federation/api/mapping/create.rs +++ b/crates/keystone/src/federation/api/mapping/create.rs @@ -55,7 +55,13 @@ pub(super) async fn create( .get_federation_provider() .create_mapping(&state, req.into()) .await?; - Ok((StatusCode::CREATED, res).into_response()) + Ok(( + StatusCode::CREATED, + Json(MappingResponse { + mapping: Mapping::from(res), + }), + ) + .into_response()) } #[cfg(test)] @@ -65,14 +71,15 @@ mod tests { http::{Request, StatusCode, header}, }; use http_body_util::BodyExt; // for `collect` - use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::federation as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::federation::{MockFederationProvider, types as provider_types}; + use crate::federation::MockFederationProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/federation/api/mapping/delete.rs b/crates/keystone/src/federation/api/mapping/delete.rs index 4adb6222..2a1836d1 100644 --- a/crates/keystone/src/federation/api/mapping/delete.rs +++ b/crates/keystone/src/federation/api/mapping/delete.rs @@ -91,9 +91,11 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::federation as provider_types; + use super::super::openapi_router; use crate::api::tests::get_mocked_state; - use crate::federation::{MockFederationProvider, types as provider_types}; + use crate::federation::MockFederationProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/federation/api/mapping/list.rs b/crates/keystone/src/federation/api/mapping/list.rs index 30c899f3..6e04f70f 100644 --- a/crates/keystone/src/federation/api/mapping/list.rs +++ b/crates/keystone/src/federation/api/mapping/list.rs @@ -91,9 +91,11 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::federation as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::federation::{MockFederationProvider, types as provider_types}; + use crate::federation::MockFederationProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/federation/api/mapping/show.rs b/crates/keystone/src/federation/api/mapping/show.rs index 73d5973d..d68f013b 100644 --- a/crates/keystone/src/federation/api/mapping/show.rs +++ b/crates/keystone/src/federation/api/mapping/show.rs @@ -14,7 +14,9 @@ //! Federation attribute mapping: show. use axum::{ + Json, extract::{Path, State}, + http::StatusCode, response::IntoResponse, }; @@ -72,7 +74,13 @@ pub(super) async fn show( None, ) .await?; - Ok(current) + Ok(( + StatusCode::OK, + Json(MappingResponse { + mapping: Mapping::from(current), + }), + ) + .into_response()) } #[cfg(test)] @@ -86,9 +94,11 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::federation as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::federation::{MockFederationProvider, types as provider_types}; + use crate::federation::MockFederationProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/federation/api/mapping/update.rs b/crates/keystone/src/federation/api/mapping/update.rs index 89649aef..8235a9e9 100644 --- a/crates/keystone/src/federation/api/mapping/update.rs +++ b/crates/keystone/src/federation/api/mapping/update.rs @@ -16,6 +16,7 @@ use axum::{ Json, extract::{Path, State}, + http::StatusCode, response::IntoResponse, }; use validator::Validate; @@ -76,7 +77,13 @@ pub(super) async fn update( .get_federation_provider() .update_mapping(&state, &id, req.into()) .await?; - Ok(res.into_response()) + Ok(( + StatusCode::OK, + Json(MappingResponse { + mapping: Mapping::from(res), + }), + ) + .into_response()) } #[cfg(test)] @@ -90,9 +97,11 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::federation as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::federation::{MockFederationProvider, types as provider_types}; + use crate::federation::MockFederationProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/federation/api/oidc.rs b/crates/keystone/src/federation/api/oidc.rs index b11c91da..53348ad8 100644 --- a/crates/keystone/src/federation/api/oidc.rs +++ b/crates/keystone/src/federation/api/oidc.rs @@ -42,10 +42,13 @@ use crate::federation::{ }; use crate::identity::IdentityApi; use crate::identity::error::IdentityProviderError; -use crate::identity::types::{FederationBuilder, FederationProtocol, UserCreateBuilder}; -use crate::identity::types::{Group, GroupCreate, GroupListParameters}; use crate::keystone::ServiceState; use crate::token::TokenApi; +use openstack_keystone_core::api::v4::auth::token::token_impl::build_api_token_v4; +use openstack_keystone_core_types::identity::{ + FederationBuilder, FederationProtocol, Group, GroupCreate, GroupListParameters, + UserCreateBuilder, +}; use super::common::{map_user_data, validate_bound_claims}; @@ -329,7 +332,7 @@ pub async fn callback( .map_err(KeystoneApiError::forbidden)?; let mut api_token = KeystoneTokenResponse { - token: token.build_api_token_v4(&state).await?, + token: build_api_token_v4(&token, &state).await?, }; let catalog: Catalog = Catalog( state diff --git a/crates/keystone/src/federation/api/types.rs b/crates/keystone/src/federation/api/types.rs index ff7b6297..f7b1360c 100644 --- a/crates/keystone/src/federation/api/types.rs +++ b/crates/keystone/src/federation/api/types.rs @@ -25,13 +25,10 @@ use openidconnect::{ IdTokenFields, StandardErrorResponse, StandardTokenResponse, }; -pub mod auth; -pub mod identity_provider; -pub mod mapping; +pub use openstack_keystone_api_types::federation::*; -pub use auth::*; -pub use identity_provider::*; -pub use mapping::*; +mod identity_provider; +mod mapping; pub(super) type OidcIdTokenFields = IdTokenFields< AllOtherClaims, diff --git a/crates/keystone/src/federation/api/types/auth.rs b/crates/keystone/src/federation/api/types/auth.rs deleted file mode 100644 index b4b407f5..00000000 --- a/crates/keystone/src/federation/api/types/auth.rs +++ /dev/null @@ -1,18 +0,0 @@ -// 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 -//! Federated auth OIDC auth types. - -pub use openstack_keystone_api_types::federation::auth::AuthCallbackParameters; -pub use openstack_keystone_api_types::federation::auth::IdentityProviderAuthRequest; -pub use openstack_keystone_api_types::federation::auth::IdentityProviderAuthResponse; diff --git a/crates/keystone/src/federation/api/types/identity_provider.rs b/crates/keystone/src/federation/api/types/identity_provider.rs index edae14b2..1e5aa4e6 100644 --- a/crates/keystone/src/federation/api/types/identity_provider.rs +++ b/crates/keystone/src/federation/api/types/identity_provider.rs @@ -12,16 +12,7 @@ // // SPDX-License-Identifier: Apache-2.0 //! Federated identity provider types. -use openstack_keystone_api_types::federation::identity_provider; - -pub use identity_provider::IdentityProvider; -pub use identity_provider::IdentityProviderCreate; -pub use identity_provider::IdentityProviderCreateRequest; -pub use identity_provider::IdentityProviderList; -pub use identity_provider::IdentityProviderListParameters; -pub use identity_provider::IdentityProviderResponse; -pub use identity_provider::IdentityProviderUpdate; -pub use identity_provider::IdentityProviderUpdateRequest; +use openstack_keystone_api_types::federation::*; use crate::api::common::{QueryParameterPagination, ResourceIdentifier}; diff --git a/crates/keystone/src/federation/api/types/mapping.rs b/crates/keystone/src/federation/api/types/mapping.rs index bfafc536..10f01866 100644 --- a/crates/keystone/src/federation/api/types/mapping.rs +++ b/crates/keystone/src/federation/api/types/mapping.rs @@ -13,20 +13,10 @@ // SPDX-License-Identifier: Apache-2.0 //! Federated attribute mapping types. -use openstack_keystone_api_types::federation::mapping; +use openstack_keystone_api_types::federation::*; use crate::api::common::{QueryParameterPagination, ResourceIdentifier}; -pub use mapping::Mapping; -pub use mapping::MappingCreate; -pub use mapping::MappingCreateRequest; -pub use mapping::MappingList; -pub use mapping::MappingListParameters; -pub use mapping::MappingResponse; -pub use mapping::MappingType; -pub use mapping::MappingUpdate; -pub use mapping::MappingUpdateRequest; - impl ResourceIdentifier for Mapping { fn get_id(&self) -> String { self.id.clone() diff --git a/crates/keystone/src/k8s_auth/api/auth.rs b/crates/keystone/src/k8s_auth/api/auth.rs index 63a82c1a..25c372f9 100644 --- a/crates/keystone/src/k8s_auth/api/auth.rs +++ b/crates/keystone/src/k8s_auth/api/auth.rs @@ -22,17 +22,20 @@ use axum::{ use utoipa_axum::{router::OpenApiRouter, routes}; use validator::Validate; +use openstack_keystone_api_types::error::KeystoneApiError; +use openstack_keystone_api_types::k8s_auth::K8sAuthRequest; +use openstack_keystone_core::api::v4::auth::token::token_impl::build_api_token_v4; +use openstack_keystone_core::k8s_auth::K8sAuthApi; +use openstack_keystone_core::keystone::ServiceState; +use openstack_keystone_core::token::TokenApi; +use openstack_keystone_core_types::scope::{Project, Scope}; + use crate::api::v4::auth::token::types::TokenResponse; use crate::api::{ - KeystoneApiError, common::get_authz_info, types::{Catalog, CatalogService}, }; use crate::catalog::CatalogApi; -use crate::common::types::{Project, Scope}; -use crate::k8s_auth::{K8sAuthApi, api::types::K8sAuthRequest}; -use crate::keystone::ServiceState; -use crate::token::TokenApi; pub(super) fn openapi_router() -> OpenApiRouter { OpenApiRouter::new().routes(routes!(post)) @@ -78,7 +81,7 @@ pub async fn post( let (authn_info, token_restriction) = state .provider .get_k8s_auth_provider() - .authenticate_by_k8s_sa_token(&state, &(req, instance_id).into()) + .authenticate_by_k8s_sa_token(&state, &req.to_provider_with_instance_id(instance_id)) .await?; authn_info.validate()?; @@ -112,7 +115,7 @@ pub async fn post( .map_err(KeystoneApiError::forbidden)?; let mut api_token = TokenResponse { - token: token.build_api_token_v4(&state).await?, + token: build_api_token_v4(&token, &state).await?, }; api_token.validate()?; diff --git a/crates/keystone/src/k8s_auth/api/error.rs b/crates/keystone/src/k8s_auth/api/error.rs deleted file mode 100644 index e30232ba..00000000 --- a/crates/keystone/src/k8s_auth/api/error.rs +++ /dev/null @@ -1,59 +0,0 @@ -// 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 -use tracing::error; - -use crate::api::error::KeystoneApiError; -use crate::k8s_auth::K8sAuthProviderError; - -/// Convert `K8sAuthProviderError` error into the [HTTP](KeystoneApiError) with -/// the expected -impl From for KeystoneApiError { - fn from(source: K8sAuthProviderError) -> Self { - error!( - "Error happened during request k8s_auth processing: {:#?}", - source - ); - match source { - K8sAuthProviderError::AudienceMismatch => Self::forbidden(source), - K8sAuthProviderError::CaCertificateUnknown => Self::forbidden(source), - K8sAuthProviderError::AuthInstanceNotActive(..) => Self::forbidden(source), - K8sAuthProviderError::AuthInstanceNotFound(x) => Self::NotFound { - resource: "k8s auth configuration".into(), - identifier: x, - }, - K8sAuthProviderError::Conflict(x) => Self::Conflict(x), - K8sAuthProviderError::FailedBoundServiceAccountName(..) => Self::forbidden(source), - K8sAuthProviderError::FailedBoundServiceAccountNamespace(..) => Self::forbidden(source), - K8sAuthProviderError::Jwt { .. } => Self::forbidden(source), - K8sAuthProviderError::ExpiredToken => Self::forbidden(source), - K8sAuthProviderError::InsecureAlgorithm => Self::forbidden(source), - K8sAuthProviderError::InvalidToken => Self::forbidden(source), - K8sAuthProviderError::RoleNotFound(x) => Self::NotFound { - resource: "k8s auth role".into(), - identifier: x, - }, - K8sAuthProviderError::RoleNotActive(..) => Self::forbidden(source), - K8sAuthProviderError::RoleInstanceOwnershipMismatch(..) => Self::forbidden(source), - K8sAuthProviderError::TokenRestrictionNotFound(x) => Self::NotFound { - resource: "token restriction".into(), - identifier: x, - }, - K8sAuthProviderError::UserNotFound(x) => Self::NotFound { - resource: "user/service account".into(), - identifier: x, - }, - other => Self::InternalError(other.to_string()), - } - } -} diff --git a/crates/keystone/src/k8s_auth/api/instance/create.rs b/crates/keystone/src/k8s_auth/api/instance/create.rs index 13a291b1..3296fa22 100644 --- a/crates/keystone/src/k8s_auth/api/instance/create.rs +++ b/crates/keystone/src/k8s_auth/api/instance/create.rs @@ -16,12 +16,13 @@ use axum::{Json, debug_handler, extract::State, http::StatusCode, response::IntoResponse}; use validator::Validate; +use openstack_keystone_api_types::k8s_auth::{ + K8sAuthInstance, K8sAuthInstanceCreateRequest, K8sAuthInstanceResponse, +}; + use crate::api::auth::Auth; use crate::api::error::KeystoneApiError; -use crate::k8s_auth::{ - K8sAuthApi, - api::types::{K8sAuthInstanceCreateRequest, K8sAuthInstanceResponse}, -}; +use crate::k8s_auth::K8sAuthApi; use crate::keystone::ServiceState; /// Create the K8s auth instance. @@ -65,7 +66,13 @@ pub(super) async fn create( .get_k8s_auth_provider() .create_auth_instance(&state, req.into()) .await?; - Ok((StatusCode::CREATED, res).into_response()) + Ok(( + StatusCode::CREATED, + Json(K8sAuthInstanceResponse { + instance: K8sAuthInstance::from(res), + }), + ) + .into_response()) } #[cfg(test)] @@ -79,13 +86,14 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_api_types::k8s_auth::{ + K8sAuthInstanceCreate, K8sAuthInstanceCreateRequest, + }; + use openstack_keystone_core_types::k8s_auth as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::k8s_auth::{ - MockK8sAuthProvider, - api::types::{K8sAuthInstanceCreate, K8sAuthInstanceCreateRequest}, - types as provider_types, - }; + use crate::k8s_auth::MockK8sAuthProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/k8s_auth/api/instance/delete.rs b/crates/keystone/src/k8s_auth/api/instance/delete.rs index 51209ea6..95c95108 100644 --- a/crates/keystone/src/k8s_auth/api/instance/delete.rs +++ b/crates/keystone/src/k8s_auth/api/instance/delete.rs @@ -93,9 +93,11 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::k8s_auth as provider_types; + use super::super::openapi_router; use crate::api::tests::get_mocked_state; - use crate::k8s_auth::{K8sAuthProviderError, MockK8sAuthProvider, types as provider_types}; + use crate::k8s_auth::{K8sAuthProviderError, MockK8sAuthProvider}; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/k8s_auth/api/instance/list.rs b/crates/keystone/src/k8s_auth/api/instance/list.rs index 6e77313c..97c385e4 100644 --- a/crates/keystone/src/k8s_auth/api/instance/list.rs +++ b/crates/keystone/src/k8s_auth/api/instance/list.rs @@ -22,8 +22,11 @@ use axum::{ use serde_json::to_value; use validator::Validate; +use openstack_keystone_api_types::k8s_auth::*; +use openstack_keystone_core_types::k8s_auth as provider_types; + use crate::api::{KeystoneApiError, auth::Auth}; -use crate::k8s_auth::{K8sAuthApi, api::types::*, types as provider_types}; +use crate::k8s_auth::K8sAuthApi; use crate::keystone::ServiceState; /// List K8s auth instances @@ -113,9 +116,11 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::k8s_auth as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::k8s_auth::{MockK8sAuthProvider, types as provider_types}; + use crate::k8s_auth::MockK8sAuthProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/k8s_auth/api/instance/show.rs b/crates/keystone/src/k8s_auth/api/instance/show.rs index 2df24933..55fd0c5c 100644 --- a/crates/keystone/src/k8s_auth/api/instance/show.rs +++ b/crates/keystone/src/k8s_auth/api/instance/show.rs @@ -14,13 +14,17 @@ //! K8s auth: show auth instances. use axum::{ + Json, extract::{Path, State}, + http::StatusCode, response::IntoResponse, }; +use openstack_keystone_api_types::k8s_auth::*; + use crate::api::auth::Auth; use crate::api::error::KeystoneApiError; -use crate::k8s_auth::{K8sAuthApi, api::types::*}; +use crate::k8s_auth::K8sAuthApi; use crate::keystone::ServiceState; /// Get single K8s auth instance. @@ -72,7 +76,13 @@ pub(super) async fn show( None, ) .await?; - Ok(current) + Ok(( + StatusCode::OK, + Json(K8sAuthInstanceResponse { + instance: K8sAuthInstance::from(current), + }), + ) + .into_response()) } #[cfg(test)] @@ -86,9 +96,11 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::k8s_auth as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::k8s_auth::{MockK8sAuthProvider, types as provider_types}; + use crate::k8s_auth::MockK8sAuthProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/k8s_auth/api/instance/update.rs b/crates/keystone/src/k8s_auth/api/instance/update.rs index 15495bd6..869e4caa 100644 --- a/crates/keystone/src/k8s_auth/api/instance/update.rs +++ b/crates/keystone/src/k8s_auth/api/instance/update.rs @@ -16,13 +16,16 @@ use axum::{ Json, extract::{Path, State}, + http::StatusCode, response::IntoResponse, }; use validator::Validate; +use openstack_keystone_api_types::k8s_auth::*; + use crate::api::auth::Auth; use crate::api::error::KeystoneApiError; -use crate::k8s_auth::{K8sAuthApi, api::types::*}; +use crate::k8s_auth::K8sAuthApi; use crate::keystone::ServiceState; /// Update single K8s auth instance. @@ -77,7 +80,13 @@ pub(super) async fn update( .get_k8s_auth_provider() .update_auth_instance(&state, &instance_id, req.into()) .await?; - Ok(res.into_response()) + Ok(( + StatusCode::OK, + Json(K8sAuthInstanceResponse { + instance: K8sAuthInstance::from(res), + }), + ) + .into_response()) } #[cfg(test)] @@ -87,14 +96,15 @@ mod tests { http::{Request, StatusCode, header}, }; use http_body_util::BodyExt; // for `collect` - use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::k8s_auth as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::k8s_auth::{MockK8sAuthProvider, types as provider_types}; + use crate::k8s_auth::MockK8sAuthProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/k8s_auth/api/role/create.rs b/crates/keystone/src/k8s_auth/api/role/create.rs index 674204bd..6bb8d68f 100644 --- a/crates/keystone/src/k8s_auth/api/role/create.rs +++ b/crates/keystone/src/k8s_auth/api/role/create.rs @@ -22,9 +22,12 @@ use axum::{ use serde_json::json; use validator::Validate; +use openstack_keystone_api_types::error::KeystoneApiError; +use openstack_keystone_api_types::k8s_auth::*; +use openstack_keystone_core_types::k8s_auth::K8sAuthRoleCreateBuilder; + use crate::api::auth::Auth; -use crate::api::error::KeystoneApiError; -use crate::k8s_auth::{K8sAuthApi, api::types::*}; +use crate::k8s_auth::K8sAuthApi; use crate::keystone::ServiceState; /// Create K8s auth role. @@ -80,9 +83,21 @@ pub(super) async fn create_nested( let res = state .provider .get_k8s_auth_provider() - .create_auth_role(&state, (req, instance_id, instance.domain_id).into()) + .create_auth_role( + &state, + K8sAuthRoleCreateBuilder::from(req) + .auth_instance_id(instance_id) + .domain_id(instance.domain_id) + .build()?, + ) .await?; - Ok((StatusCode::CREATED, res).into_response()) + Ok(( + StatusCode::CREATED, + Json(K8sAuthRoleResponse { + role: K8sAuthRole::from(res), + }), + ) + .into_response()) } #[cfg(test)] @@ -92,14 +107,15 @@ mod tests { http::{Request, StatusCode, header}, }; use http_body_util::BodyExt; // for `collect` - use tower::ServiceExt; // for `call`, `oneshot`, and `ready` use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::k8s_auth as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::k8s_auth::{MockK8sAuthProvider, types as provider_types}; + use crate::k8s_auth::MockK8sAuthProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/k8s_auth/api/role/delete.rs b/crates/keystone/src/k8s_auth/api/role/delete.rs index cffba6a3..af76f49e 100644 --- a/crates/keystone/src/k8s_auth/api/role/delete.rs +++ b/crates/keystone/src/k8s_auth/api/role/delete.rs @@ -145,9 +145,11 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::k8s_auth as provider_types; + use super::super::*; use crate::api::tests::get_mocked_state; - use crate::k8s_auth::{MockK8sAuthProvider, types as provider_types}; + use crate::k8s_auth::MockK8sAuthProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/k8s_auth/api/role/list.rs b/crates/keystone/src/k8s_auth/api/role/list.rs index 0697fde0..e00ab854 100644 --- a/crates/keystone/src/k8s_auth/api/role/list.rs +++ b/crates/keystone/src/k8s_auth/api/role/list.rs @@ -22,9 +22,12 @@ use axum::{ use serde_json::to_value; use validator::Validate; +use openstack_keystone_api_types::k8s_auth::*; +use openstack_keystone_core::k8s_auth::K8sAuthApi; +use openstack_keystone_core::keystone::ServiceState; +use openstack_keystone_core_types::k8s_auth as provider_types; + use crate::api::{KeystoneApiError, auth::Auth}; -use crate::k8s_auth::{K8sAuthApi, api::types::*, types as provider_types}; -use crate::keystone::ServiceState; /// List K8 auth roles. /// @@ -186,9 +189,11 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::k8s_auth as provider_types; + use super::{super::*, *}; use crate::api::tests::get_mocked_state; - use crate::k8s_auth::{MockK8sAuthProvider, types as provider_types}; + use crate::k8s_auth::MockK8sAuthProvider; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/k8s_auth/api/role/show.rs b/crates/keystone/src/k8s_auth/api/role/show.rs index 36cf30b8..6e7e7f82 100644 --- a/crates/keystone/src/k8s_auth/api/role/show.rs +++ b/crates/keystone/src/k8s_auth/api/role/show.rs @@ -14,16 +14,17 @@ //! K8s auth role: show. use axum::{ + Json, extract::{Path, State}, + http::StatusCode, response::IntoResponse, }; +use openstack_keystone_api_types::k8s_auth::*; + use crate::api::auth::Auth; use crate::api::error::KeystoneApiError; -use crate::k8s_auth::{ - K8sAuthApi, - api::types::{K8sAuthRolePathParams, K8sAuthRoleResponse}, -}; +use crate::k8s_auth::K8sAuthApi; use crate::keystone::ServiceState; /// Get single K8s auth role of a instance. @@ -74,7 +75,13 @@ pub(super) async fn show_nested( None, ) .await?; - Ok(current) + Ok(( + StatusCode::OK, + Json(K8sAuthRoleResponse { + role: K8sAuthRole::from(current), + }), + ) + .into_response()) } /// Get single K8s auth role. @@ -126,7 +133,13 @@ pub(super) async fn show( None, ) .await?; - Ok(current) + Ok(( + StatusCode::OK, + Json(K8sAuthRoleResponse { + role: K8sAuthRole::from(current), + }), + ) + .into_response()) } #[cfg(test)] @@ -140,9 +153,11 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::k8s_auth as provider_types; + use super::{super::openapi_router, *}; use crate::api::tests::get_mocked_state; - use crate::k8s_auth::{MockK8sAuthProvider, api::types::K8sAuthRole, types as provider_types}; + use crate::k8s_auth::{MockK8sAuthProvider, api::types::K8sAuthRole}; use crate::provider::Provider; #[tokio::test] diff --git a/crates/keystone/src/k8s_auth/api/role/update.rs b/crates/keystone/src/k8s_auth/api/role/update.rs index 3f102cd8..3c673592 100644 --- a/crates/keystone/src/k8s_auth/api/role/update.rs +++ b/crates/keystone/src/k8s_auth/api/role/update.rs @@ -16,16 +16,18 @@ use axum::{ Json, extract::{Path, State}, + http::StatusCode, response::IntoResponse, }; use validator::Validate; +use openstack_keystone_api_types::k8s_auth::{ + K8sAuthRole, K8sAuthRolePathParams, K8sAuthRoleResponse, K8sAuthRoleUpdateRequest, +}; + use crate::api::auth::Auth; use crate::api::error::KeystoneApiError; -use crate::k8s_auth::{ - K8sAuthApi, - api::types::{K8sAuthRolePathParams, K8sAuthRoleResponse, K8sAuthRoleUpdateRequest}, -}; +use crate::k8s_auth::K8sAuthApi; use crate::keystone::ServiceState; /// Update K8s auth role of an instance. @@ -75,7 +77,13 @@ pub(super) async fn update_nested( .get_k8s_auth_provider() .update_auth_role(&state, &path_params.id, req.into()) .await?; - Ok(res.into_response()) + Ok(( + StatusCode::OK, + Json(K8sAuthRoleResponse { + role: K8sAuthRole::from(res), + }), + ) + .into_response()) } /// Update K8s auth role. @@ -127,7 +135,13 @@ pub(super) async fn update( .get_k8s_auth_provider() .update_auth_role(&state, &id, req.into()) .await?; - Ok(res.into_response()) + Ok(( + StatusCode::OK, + Json(K8sAuthRoleResponse { + role: K8sAuthRole::from(res), + }), + ) + .into_response()) } #[cfg(test)] @@ -141,11 +155,11 @@ mod tests { use tower_http::trace::TraceLayer; use tracing_test::traced_test; + use openstack_keystone_core_types::k8s_auth as provider_types; + use super::{super::*, *}; use crate::api::tests::get_mocked_state; - use crate::k8s_auth::{ - MockK8sAuthProvider, api::types::K8sAuthRoleUpdate, types as provider_types, - }; + use crate::k8s_auth::{MockK8sAuthProvider, api::types::K8sAuthRoleUpdate}; use crate::provider::Provider; #[tokio::test] diff --git a/crates/resource-sql/Cargo.toml b/crates/resource-sql/Cargo.toml index 3acf3f60..e550d45b 100644 --- a/crates/resource-sql/Cargo.toml +++ b/crates/resource-sql/Cargo.toml @@ -13,6 +13,7 @@ exclude.workspace = true [dependencies] async-trait.workspace = true openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } sea-orm.workspace = true serde_json.workspace = true tracing.workspace = true diff --git a/crates/resource-sql/src/domain.rs b/crates/resource-sql/src/domain.rs index 90ca0ff6..9429bcba 100644 --- a/crates/resource-sql/src/domain.rs +++ b/crates/resource-sql/src/domain.rs @@ -16,10 +16,8 @@ use serde_json::{Value, json}; use tracing::error; use uuid::Uuid; -use openstack_keystone_core::resource::{ - ResourceProviderError, - types::{Domain, DomainBuilder, DomainCreate}, -}; +use openstack_keystone_core::resource::ResourceProviderError; +use openstack_keystone_core_types::resource::{Domain, DomainBuilder, DomainCreate}; mod create; mod delete; diff --git a/crates/resource-sql/src/domain/create.rs b/crates/resource-sql/src/domain/create.rs index 7e308ae8..a6cb1931 100644 --- a/crates/resource-sql/src/domain/create.rs +++ b/crates/resource-sql/src/domain/create.rs @@ -16,10 +16,8 @@ use sea_orm::ConnectionTrait; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::resource::{ - ResourceProviderError, - types::{Domain, DomainCreate}, -}; +use openstack_keystone_core::resource::ResourceProviderError; +use openstack_keystone_core_types::resource::{Domain, DomainCreate}; use crate::entity::project as db_project; diff --git a/crates/resource-sql/src/domain/get.rs b/crates/resource-sql/src/domain/get.rs index ebf929ae..f8b4ec6c 100644 --- a/crates/resource-sql/src/domain/get.rs +++ b/crates/resource-sql/src/domain/get.rs @@ -17,7 +17,8 @@ use sea_orm::entity::*; use sea_orm::query::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::resource::{ResourceProviderError, types::Domain}; +use openstack_keystone_core::resource::ResourceProviderError; +use openstack_keystone_core_types::resource::Domain; use crate::entity::{prelude::Project as DbProject, project as db_project}; diff --git a/crates/resource-sql/src/domain/list.rs b/crates/resource-sql/src/domain/list.rs index b23eeb48..fb064c84 100644 --- a/crates/resource-sql/src/domain/list.rs +++ b/crates/resource-sql/src/domain/list.rs @@ -18,10 +18,8 @@ use sea_orm::query::*; use sea_orm::{Cursor, SelectModel}; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::resource::{ - ResourceProviderError, - types::{Domain, DomainListParameters}, -}; +use openstack_keystone_core::resource::ResourceProviderError; +use openstack_keystone_core_types::resource::{Domain, DomainListParameters}; use crate::entity::{prelude::Project as DbProject, project as db_project}; diff --git a/crates/resource-sql/src/lib.rs b/crates/resource-sql/src/lib.rs index 70782646..7537a033 100644 --- a/crates/resource-sql/src/lib.rs +++ b/crates/resource-sql/src/lib.rs @@ -16,9 +16,8 @@ use async_trait::async_trait; use openstack_keystone_core::keystone::ServiceState; -use openstack_keystone_core::resource::{ - ResourceProviderError, backend::ResourceBackend, types::*, -}; +use openstack_keystone_core::resource::{ResourceProviderError, backend::ResourceBackend}; +use openstack_keystone_core_types::resource::*; mod domain; pub mod entity; diff --git a/crates/resource-sql/src/project.rs b/crates/resource-sql/src/project.rs index b320aab0..8826498c 100644 --- a/crates/resource-sql/src/project.rs +++ b/crates/resource-sql/src/project.rs @@ -17,10 +17,8 @@ use serde_json::json; use tracing::error; use uuid::Uuid; -use openstack_keystone_core::resource::{ - ResourceProviderError, - types::{Project, ProjectBuilder, ProjectCreate}, -}; +use openstack_keystone_core::resource::ResourceProviderError; +use openstack_keystone_core_types::resource::{Project, ProjectBuilder, ProjectCreate}; mod create; mod delete; diff --git a/crates/resource-sql/src/project/create.rs b/crates/resource-sql/src/project/create.rs index 63b6bf31..4a29e0c8 100644 --- a/crates/resource-sql/src/project/create.rs +++ b/crates/resource-sql/src/project/create.rs @@ -16,10 +16,8 @@ use sea_orm::ConnectionTrait; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::resource::{ - ResourceProviderError, - types::{Project, ProjectCreate}, -}; +use openstack_keystone_core::resource::ResourceProviderError; +use openstack_keystone_core_types::resource::{Project, ProjectCreate}; use crate::entity::project as db_project; diff --git a/crates/resource-sql/src/project/get.rs b/crates/resource-sql/src/project/get.rs index 0ca83a79..46a89f78 100644 --- a/crates/resource-sql/src/project/get.rs +++ b/crates/resource-sql/src/project/get.rs @@ -17,7 +17,8 @@ use sea_orm::entity::*; use sea_orm::query::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::resource::{ResourceProviderError, types::Project}; +use openstack_keystone_core::resource::ResourceProviderError; +use openstack_keystone_core_types::resource::Project; use crate::entity::{prelude::Project as DbProject, project as db_project}; diff --git a/crates/resource-sql/src/project/list.rs b/crates/resource-sql/src/project/list.rs index c176860d..544e13da 100644 --- a/crates/resource-sql/src/project/list.rs +++ b/crates/resource-sql/src/project/list.rs @@ -18,10 +18,8 @@ use sea_orm::query::*; use sea_orm::{Cursor, SelectModel}; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::resource::{ - ResourceProviderError, - types::{Project, ProjectListParameters}, -}; +use openstack_keystone_core::resource::ResourceProviderError; +use openstack_keystone_core_types::resource::{Project, ProjectListParameters}; use crate::entity::{prelude::Project as DbProject, project as db_project}; diff --git a/crates/resource-sql/src/project/tree.rs b/crates/resource-sql/src/project/tree.rs index 41a761a2..f6719d5c 100644 --- a/crates/resource-sql/src/project/tree.rs +++ b/crates/resource-sql/src/project/tree.rs @@ -16,7 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::resource::{ResourceProviderError, types::Project}; +use openstack_keystone_core::resource::ResourceProviderError; +use openstack_keystone_core_types::resource::Project; use crate::entity::prelude::Project as DbProject; @@ -49,7 +50,7 @@ pub async fn get_project_parents>( mod tests { use sea_orm::{DatabaseBackend, MockDatabase, Transaction}; - use openstack_keystone_core::resource::types::Project; + use openstack_keystone_core_types::resource::Project; use crate::entity::project; diff --git a/crates/revoke-sql/Cargo.toml b/crates/revoke-sql/Cargo.toml index a4cf40b8..988b54f8 100644 --- a/crates/revoke-sql/Cargo.toml +++ b/crates/revoke-sql/Cargo.toml @@ -14,6 +14,7 @@ exclude.workspace = true async-trait.workspace = true chrono.workspace = true openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } sea-orm.workspace = true serde_json.workspace = true tracing.workspace = true diff --git a/crates/revoke-sql/src/create.rs b/crates/revoke-sql/src/create.rs index a80e7f55..2854b049 100644 --- a/crates/revoke-sql/src/create.rs +++ b/crates/revoke-sql/src/create.rs @@ -18,7 +18,7 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::revoke::{RevocationEvent, RevocationEventCreate}; +use openstack_keystone_core_types::revoke::{RevocationEvent, RevocationEventCreate}; use crate::entity::revocation_event as db_revocation_event; diff --git a/crates/revoke-sql/src/lib.rs b/crates/revoke-sql/src/lib.rs index 0f9e4ea0..e41b58f2 100644 --- a/crates/revoke-sql/src/lib.rs +++ b/crates/revoke-sql/src/lib.rs @@ -16,8 +16,9 @@ use async_trait::async_trait; use openstack_keystone_core::keystone::ServiceState; -use openstack_keystone_core::revoke::{RevokeProviderError, backend::RevokeBackend, types::*}; -use openstack_keystone_core::token::types::Token; +use openstack_keystone_core::revoke::{RevokeProviderError, backend::RevokeBackend}; +use openstack_keystone_core_types::revoke::*; +use openstack_keystone_core_types::token::Token; use crate::entity::revocation_event as db_revocation_event; diff --git a/crates/revoke-sql/src/list.rs b/crates/revoke-sql/src/list.rs index d5271c50..9649fce0 100644 --- a/crates/revoke-sql/src/list.rs +++ b/crates/revoke-sql/src/list.rs @@ -19,7 +19,7 @@ use sea_orm::query::*; use openstack_keystone_core::error::DbContextExt; use openstack_keystone_core::revoke::RevokeProviderError; -use openstack_keystone_core::revoke::types::{RevocationEvent, RevocationEventListParameters}; +use openstack_keystone_core_types::revoke::{RevocationEvent, RevocationEventListParameters}; use crate::entity::{ prelude::RevocationEvent as DbRevocationEvent, revocation_event as db_revocation_event, @@ -162,7 +162,7 @@ mod tests { use sea_orm::{DatabaseBackend, IntoMockRow, MockDatabase, Transaction}; use std::collections::BTreeMap; - use openstack_keystone_core::revoke::types::RevocationEventListParametersBuilder; + use openstack_keystone_core_types::revoke::RevocationEventListParametersBuilder; use super::super::tests::get_mock; use super::*; diff --git a/crates/role-sql/Cargo.toml b/crates/role-sql/Cargo.toml index 3befe4e9..ea562a7f 100644 --- a/crates/role-sql/Cargo.toml +++ b/crates/role-sql/Cargo.toml @@ -13,6 +13,7 @@ exclude.workspace = true [dependencies] async-trait.workspace = true openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } sea-orm.workspace = true serde_json.workspace = true tracing.workspace = true diff --git a/crates/role-sql/src/lib.rs b/crates/role-sql/src/lib.rs index e75945d0..920d98b4 100644 --- a/crates/role-sql/src/lib.rs +++ b/crates/role-sql/src/lib.rs @@ -18,7 +18,7 @@ use std::collections::{BTreeMap, BTreeSet, HashSet}; use openstack_keystone_core::keystone::ServiceState; use openstack_keystone_core::role::RoleProviderError; use openstack_keystone_core::role::backend::RoleBackend; -use openstack_keystone_core::role::types::*; +use openstack_keystone_core_types::role::*; pub mod entity; mod implied_role; diff --git a/crates/role-sql/src/role.rs b/crates/role-sql/src/role.rs index f2305a4b..aba6023e 100644 --- a/crates/role-sql/src/role.rs +++ b/crates/role-sql/src/role.rs @@ -17,10 +17,8 @@ use serde_json::{Value, json}; use tracing::error; use uuid::Uuid; -use openstack_keystone_core::role::{ - RoleProviderError, - types::{Role, RoleBuilder, RoleCreate, RoleRef}, -}; +use openstack_keystone_core::role::RoleProviderError; +use openstack_keystone_core_types::role::{Role, RoleBuilder, RoleCreate, RoleRef}; mod create; mod delete; diff --git a/crates/role-sql/src/role/create.rs b/crates/role-sql/src/role/create.rs index 191e03a2..b90f220b 100644 --- a/crates/role-sql/src/role/create.rs +++ b/crates/role-sql/src/role/create.rs @@ -16,10 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::role::{ - RoleProviderError, - types::role::{Role, RoleCreate}, -}; +use openstack_keystone_core::role::RoleProviderError; +use openstack_keystone_core_types::role::{Role, RoleCreate}; use crate::entity::role as db_role; diff --git a/crates/role-sql/src/role/get.rs b/crates/role-sql/src/role/get.rs index 71d86847..e8c9a52d 100644 --- a/crates/role-sql/src/role/get.rs +++ b/crates/role-sql/src/role/get.rs @@ -16,7 +16,8 @@ use sea_orm::DatabaseConnection; use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::role::{RoleProviderError, types::Role}; +use openstack_keystone_core::role::RoleProviderError; +use openstack_keystone_core_types::role::Role; use crate::entity::{prelude::Role as DbRole, role as db_role}; @@ -34,7 +35,7 @@ pub async fn get>( pub(super) mod tests { use sea_orm::{DatabaseBackend, MockDatabase, Transaction}; - use openstack_keystone_core::role::types::RoleBuilder; + use openstack_keystone_core_types::role::RoleBuilder; use super::*; use crate::role::tests::get_role_mock; diff --git a/crates/role-sql/src/role/list.rs b/crates/role-sql/src/role/list.rs index 4656d6bc..19ed2504 100644 --- a/crates/role-sql/src/role/list.rs +++ b/crates/role-sql/src/role/list.rs @@ -17,10 +17,8 @@ use sea_orm::entity::*; use sea_orm::query::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::role::{ - RoleProviderError, - types::{Role, RoleListParameters}, -}; +use openstack_keystone_core::role::RoleProviderError; +use openstack_keystone_core_types::role::{Role, RoleListParameters}; use crate::entity::{prelude::Role as DbRole, role as db_role}; use crate::role::NULL_DOMAIN_ID; @@ -52,7 +50,7 @@ pub async fn list( pub(super) mod tests { use sea_orm::{DatabaseBackend, MockDatabase, Transaction}; - use openstack_keystone_core::role::types::RoleBuilder; + use openstack_keystone_core_types::role::RoleBuilder; use super::*; use crate::role::tests::get_role_mock; diff --git a/crates/token-fernet/Cargo.toml b/crates/token-fernet/Cargo.toml index 3053a790..d303847d 100644 --- a/crates/token-fernet/Cargo.toml +++ b/crates/token-fernet/Cargo.toml @@ -21,6 +21,7 @@ fernet = { workspace = true, features = ["rustcrypto"] } itertools.workspace = true openstack-keystone-config = { version = "0.1", path = "../config" } openstack-keystone-core = { version = "0.1", path = "../core/"} +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } nix = { workspace = true, features = ["fs", "user"] } rmp.workspace = true scopeguard.workspace = true diff --git a/crates/token-fernet/src/application_credential.rs b/crates/token-fernet/src/application_credential.rs index 240b5976..2620663a 100644 --- a/crates/token-fernet/src/application_credential.rs +++ b/crates/token-fernet/src/application_credential.rs @@ -15,7 +15,7 @@ use rmp::{decode::read_pfix, encode::write_pfix}; use std::io::Write; -use openstack_keystone_core::token::types::ApplicationCredentialPayload; +use openstack_keystone_core_types::token::ApplicationCredentialPayload; use crate::{FernetDriverError, FernetTokenProvider, MsgPackToken, utils}; diff --git a/crates/token-fernet/src/domain_scoped.rs b/crates/token-fernet/src/domain_scoped.rs index bae91c00..75cb22c0 100644 --- a/crates/token-fernet/src/domain_scoped.rs +++ b/crates/token-fernet/src/domain_scoped.rs @@ -15,7 +15,7 @@ use rmp::{decode::read_pfix, encode::write_pfix}; use std::io::Write; -use openstack_keystone_core::token::types::DomainScopePayload; +use openstack_keystone_core_types::token::DomainScopePayload; use crate::{FernetDriverError, FernetTokenProvider, MsgPackToken, utils}; diff --git a/crates/token-fernet/src/federation_domain_scoped.rs b/crates/token-fernet/src/federation_domain_scoped.rs index dee193d3..193a01fe 100644 --- a/crates/token-fernet/src/federation_domain_scoped.rs +++ b/crates/token-fernet/src/federation_domain_scoped.rs @@ -15,7 +15,7 @@ use rmp::{decode::read_pfix, encode::write_pfix}; use std::io::Write; -use openstack_keystone_core::token::types::FederationDomainScopePayload; +use openstack_keystone_core_types::token::FederationDomainScopePayload; use crate::{FernetDriverError, FernetTokenProvider, MsgPackToken, utils}; diff --git a/crates/token-fernet/src/federation_project_scoped.rs b/crates/token-fernet/src/federation_project_scoped.rs index cb55be7e..e1dbcc92 100644 --- a/crates/token-fernet/src/federation_project_scoped.rs +++ b/crates/token-fernet/src/federation_project_scoped.rs @@ -15,7 +15,7 @@ use rmp::{decode::read_pfix, encode::write_pfix}; use std::io::Write; -use openstack_keystone_core::token::types::FederationProjectScopePayload; +use openstack_keystone_core_types::token::FederationProjectScopePayload; use crate::{FernetDriverError, FernetTokenProvider, MsgPackToken, utils}; diff --git a/crates/token-fernet/src/federation_unscoped.rs b/crates/token-fernet/src/federation_unscoped.rs index cb7e82ce..1db6edb2 100644 --- a/crates/token-fernet/src/federation_unscoped.rs +++ b/crates/token-fernet/src/federation_unscoped.rs @@ -15,7 +15,7 @@ use rmp::{decode::read_pfix, encode::write_pfix}; use std::io::Write; -use openstack_keystone_core::token::types::FederationUnscopedPayload; +use openstack_keystone_core_types::token::FederationUnscopedPayload; use crate::{FernetDriverError, FernetTokenProvider, MsgPackToken, utils}; diff --git a/crates/token-fernet/src/lib.rs b/crates/token-fernet/src/lib.rs index 790c430c..4e88b776 100644 --- a/crates/token-fernet/src/lib.rs +++ b/crates/token-fernet/src/lib.rs @@ -33,14 +33,14 @@ use tracing::trace; use validator::Validate; use openstack_keystone_config::Config; -use openstack_keystone_core::token::types::{ - application_credential::ApplicationCredentialPayload, domain_scoped::DomainScopePayload, - federation_domain_scoped::FederationDomainScopePayload, - federation_project_scoped::FederationProjectScopePayload, - federation_unscoped::FederationUnscopedPayload, project_scoped::ProjectScopePayload, - restricted::RestrictedPayload, trust::TrustPayload, unscoped::UnscopedPayload, *, -}; use openstack_keystone_core::token::{TokenProviderError, backend::TokenBackend}; +use openstack_keystone_core_types::token::*; +// application_credential::ApplicationCredentialPayload, domain_scoped::DomainScopePayload, +// federation_domain_scoped::FederationDomainScopePayload, +// federation_project_scoped::FederationProjectScopePayload, +// federation_unscoped::FederationUnscopedPayload, project_scoped::ProjectScopePayload, +// restricted::RestrictedPayload, trust::TrustPayload, unscoped::UnscopedPayload, *, +//}; use utils::FernetUtils; mod application_credential; diff --git a/crates/token-fernet/src/project_scoped.rs b/crates/token-fernet/src/project_scoped.rs index 6213fc36..2dda63de 100644 --- a/crates/token-fernet/src/project_scoped.rs +++ b/crates/token-fernet/src/project_scoped.rs @@ -15,7 +15,7 @@ use rmp::{decode::read_pfix, encode::write_pfix}; use std::io::Write; -use openstack_keystone_core::token::types::ProjectScopePayload; +use openstack_keystone_core_types::token::ProjectScopePayload; use crate::{FernetDriverError, FernetTokenProvider, MsgPackToken, utils}; diff --git a/crates/token-fernet/src/restricted.rs b/crates/token-fernet/src/restricted.rs index f827f518..cc58c484 100644 --- a/crates/token-fernet/src/restricted.rs +++ b/crates/token-fernet/src/restricted.rs @@ -16,7 +16,7 @@ use rmp::{decode::read_pfix, encode::write_pfix}; use std::io::Write; -use openstack_keystone_core::token::types::RestrictedPayload; +use openstack_keystone_core_types::token::RestrictedPayload; use crate::{FernetDriverError, FernetTokenProvider, MsgPackToken, utils}; diff --git a/crates/token-fernet/src/system_scoped.rs b/crates/token-fernet/src/system_scoped.rs index 3ceff3c4..ae448ebb 100644 --- a/crates/token-fernet/src/system_scoped.rs +++ b/crates/token-fernet/src/system_scoped.rs @@ -15,7 +15,7 @@ use rmp::{decode::read_pfix, encode::write_pfix}; use std::io::Write; -use openstack_keystone_core::token::types::SystemScopePayload; +use openstack_keystone_core_types::token::SystemScopePayload; use crate::{FernetDriverError, FernetTokenProvider, MsgPackToken, utils}; diff --git a/crates/token-fernet/src/trust.rs b/crates/token-fernet/src/trust.rs index 0d5ff7b3..7f820d05 100644 --- a/crates/token-fernet/src/trust.rs +++ b/crates/token-fernet/src/trust.rs @@ -15,7 +15,7 @@ use rmp::{decode::read_pfix, encode::write_pfix}; use std::io::Write; -use openstack_keystone_core::token::types::TrustPayload; +use openstack_keystone_core_types::token::TrustPayload; use crate::{FernetDriverError, FernetTokenProvider, MsgPackToken, utils}; diff --git a/crates/token-fernet/src/unscoped.rs b/crates/token-fernet/src/unscoped.rs index 46864600..080b68c7 100644 --- a/crates/token-fernet/src/unscoped.rs +++ b/crates/token-fernet/src/unscoped.rs @@ -15,7 +15,7 @@ use rmp::{decode::read_pfix, encode::write_pfix}; use std::io::Write; -use openstack_keystone_core::token::types::UnscopedPayload; +use openstack_keystone_core_types::token::UnscopedPayload; use crate::{FernetDriverError, FernetTokenProvider, MsgPackToken, utils}; diff --git a/crates/token-restriction-sql/Cargo.toml b/crates/token-restriction-sql/Cargo.toml index 2277af1a..48a1b9d3 100644 --- a/crates/token-restriction-sql/Cargo.toml +++ b/crates/token-restriction-sql/Cargo.toml @@ -13,6 +13,7 @@ exclude.workspace = true [dependencies] async-trait.workspace = true openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } sea-orm.workspace = true tokio = { workspace = true, features = ["macros"] } tracing.workspace = true diff --git a/crates/token-restriction-sql/src/create.rs b/crates/token-restriction-sql/src/create.rs index 046dd214..0f94c74e 100644 --- a/crates/token-restriction-sql/src/create.rs +++ b/crates/token-restriction-sql/src/create.rs @@ -19,7 +19,7 @@ use sea_orm::entity::*; use openstack_keystone_core::error::DbContextExt; use openstack_keystone_core::token::error::TokenProviderError; -use openstack_keystone_core::token::types::*; +use openstack_keystone_core_types::token::*; use crate::entity::{ prelude::TokenRestrictionRoleAssociation as DbTokenRestrictionRoleAssociation, diff --git a/crates/token-restriction-sql/src/get.rs b/crates/token-restriction-sql/src/get.rs index f9a1a7ac..6f68e399 100644 --- a/crates/token-restriction-sql/src/get.rs +++ b/crates/token-restriction-sql/src/get.rs @@ -18,7 +18,7 @@ use sea_orm::query::*; use openstack_keystone_core::error::DbContextExt; use openstack_keystone_core::token::error::TokenProviderError; -use openstack_keystone_core::token::types::TokenRestriction; +use openstack_keystone_core_types::token::TokenRestriction; use crate::FromModelWithRoleAssociation; use crate::entity::prelude::{ diff --git a/crates/token-restriction-sql/src/lib.rs b/crates/token-restriction-sql/src/lib.rs index addd2292..d5ab59e1 100644 --- a/crates/token-restriction-sql/src/lib.rs +++ b/crates/token-restriction-sql/src/lib.rs @@ -17,7 +17,7 @@ use async_trait::async_trait; use openstack_keystone_core::keystone::ServiceState; use openstack_keystone_core::token::TokenProviderError; use openstack_keystone_core::token::backend::TokenRestrictionBackend; -use openstack_keystone_core::token::types::*; +use openstack_keystone_core_types::token::*; use crate::entity::{token_restriction, token_restriction_role_association}; diff --git a/crates/token-restriction-sql/src/list.rs b/crates/token-restriction-sql/src/list.rs index ed433903..a1639a2e 100644 --- a/crates/token-restriction-sql/src/list.rs +++ b/crates/token-restriction-sql/src/list.rs @@ -19,7 +19,7 @@ use sea_orm::query::*; use openstack_keystone_core::error::DbContextExt; use openstack_keystone_core::token::error::TokenProviderError; -use openstack_keystone_core::token::types::{TokenRestriction, TokenRestrictionListParameters}; +use openstack_keystone_core_types::token::{TokenRestriction, TokenRestrictionListParameters}; use crate::FromModelWithRoleAssociation; use crate::entity::{ diff --git a/crates/token-restriction-sql/src/update.rs b/crates/token-restriction-sql/src/update.rs index 3e0478d9..c8370166 100644 --- a/crates/token-restriction-sql/src/update.rs +++ b/crates/token-restriction-sql/src/update.rs @@ -21,7 +21,7 @@ use std::collections::BTreeSet; use openstack_keystone_core::error::DbContextExt; use openstack_keystone_core::token::error::TokenProviderError; -use openstack_keystone_core::token::types::*; +use openstack_keystone_core_types::token::*; use crate::entity::{ prelude::{ diff --git a/crates/trust-sql/Cargo.toml b/crates/trust-sql/Cargo.toml index 6f277bff..1c67e417 100644 --- a/crates/trust-sql/Cargo.toml +++ b/crates/trust-sql/Cargo.toml @@ -14,6 +14,7 @@ exclude.workspace = true async-trait.workspace = true chrono.workspace = true openstack-keystone-core = { version = "0.1", path = "../core" } +openstack-keystone-core-types = { version = "0.1", path = "../core-types" } sea-orm.workspace = true serde_json.workspace = true tokio = { workspace = true, features = ["macros"] } diff --git a/crates/trust-sql/src/lib.rs b/crates/trust-sql/src/lib.rs index e95cd10a..504a8e25 100644 --- a/crates/trust-sql/src/lib.rs +++ b/crates/trust-sql/src/lib.rs @@ -16,8 +16,9 @@ use async_trait::async_trait; use openstack_keystone_core::keystone::ServiceState; +use openstack_keystone_core::trust::TrustProviderError; use openstack_keystone_core::trust::backend::TrustBackend; -use openstack_keystone_core::trust::{TrustProviderError, types::*}; +use openstack_keystone_core_types::trust::*; pub mod entity; mod trust; diff --git a/crates/trust-sql/src/trust.rs b/crates/trust-sql/src/trust.rs index 3d18e6f5..bd30087f 100644 --- a/crates/trust-sql/src/trust.rs +++ b/crates/trust-sql/src/trust.rs @@ -16,11 +16,9 @@ use chrono::DateTime; use serde_json::Value; use tracing::error; -use openstack_keystone_core::role::types::RoleRef; -use openstack_keystone_core::trust::{ - TrustProviderError, - types::{Trust, TrustBuilder}, -}; +use openstack_keystone_core::trust::TrustProviderError; +use openstack_keystone_core_types::role::RoleRef; +use openstack_keystone_core_types::trust::*; use crate::entity::{trust as db_trust, trust_role as db_trust_role}; diff --git a/crates/trust-sql/src/trust/get.rs b/crates/trust-sql/src/trust/get.rs index d44f1990..480bd94e 100644 --- a/crates/trust-sql/src/trust/get.rs +++ b/crates/trust-sql/src/trust/get.rs @@ -17,8 +17,9 @@ use sea_orm::entity::*; use sea_orm::query::*; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::role::types::RoleRef; -use openstack_keystone_core::trust::{TrustProviderError, types::Trust}; +use openstack_keystone_core::trust::TrustProviderError; +use openstack_keystone_core_types::role::RoleRef; +use openstack_keystone_core_types::trust::Trust; use crate::entity::{ prelude::{Trust as DbTrust, TrustRole as DbTrustRole}, diff --git a/crates/trust-sql/src/trust/list.rs b/crates/trust-sql/src/trust/list.rs index 1277a64a..711b71f1 100644 --- a/crates/trust-sql/src/trust/list.rs +++ b/crates/trust-sql/src/trust/list.rs @@ -18,11 +18,9 @@ use sea_orm::query::*; use sea_orm::{Cursor, SelectModel}; use openstack_keystone_core::error::DbContextExt; -use openstack_keystone_core::role::types::RoleRef; -use openstack_keystone_core::trust::{ - TrustProviderError, - types::{Trust, TrustListParameters}, -}; +use openstack_keystone_core::trust::TrustProviderError; +use openstack_keystone_core_types::role::RoleRef; +use openstack_keystone_core_types::trust::*; use crate::entity::{ prelude::{Trust as DbTrust, TrustRole as DbTrustRole}, diff --git a/crates/webauthn/Cargo.toml b/crates/webauthn/Cargo.toml index ea268981..3194c9ca 100644 --- a/crates/webauthn/Cargo.toml +++ b/crates/webauthn/Cargo.toml @@ -15,8 +15,9 @@ base64.workspace = true chrono.workspace = true derive_builder.workspace = true eyre.workspace = true -openstack-keystone-api-types = { version = "0.1", features = ["validate"], path = "../api-types/" } +openstack-keystone-api-types = { version = "0.1", features = ["openapi", "validate", "conv"], path = "../api-types/" } openstack-keystone-core = { version = "0.1", path = "../core", features = ["api"] } +openstack-keystone-core-types = { version = "0.1", path = "../core-types/" } sea-orm = { workspace = true } serde.workspace = true serde_json.workspace = true diff --git a/crates/webauthn/src/api/auth/finish.rs b/crates/webauthn/src/api/auth/finish.rs index f5f7ca05..01e55795 100644 --- a/crates/webauthn/src/api/auth/finish.rs +++ b/crates/webauthn/src/api/auth/finish.rs @@ -23,8 +23,9 @@ use crate::{ WebauthnApi, WebauthnError, api::types::{CombinedExtensionState, auth::*}, }; +use openstack_keystone_api_types::error::KeystoneApiError; use openstack_keystone_api_types::v4::auth::token::TokenResponse; -use openstack_keystone_core::api::error::KeystoneApiError; +use openstack_keystone_core::api::v4::auth::token::token_impl::build_api_token_v4; use openstack_keystone_core::auth::{AuthenticatedInfo, AuthenticationError, AuthzInfo}; use openstack_keystone_core::identity::IdentityApi; use openstack_keystone_core::token::TokenApi; @@ -160,7 +161,7 @@ pub async fn finish( )?; let api_token = TokenResponse { - token: token.build_api_token_v4(&state.core).await?, + token: build_api_token_v4(&token, &state.core).await?, }; Ok(( StatusCode::OK, diff --git a/crates/webauthn/src/api/auth/start.rs b/crates/webauthn/src/api/auth/start.rs index 6648ba56..7a990a38 100644 --- a/crates/webauthn/src/api/auth/start.rs +++ b/crates/webauthn/src/api/auth/start.rs @@ -17,7 +17,7 @@ use axum::{Json, extract::State, response::IntoResponse}; use tracing::debug; use validator::Validate; -use openstack_keystone_core::api::KeystoneApiError; +use openstack_keystone_api_types::error::KeystoneApiError; use crate::{ WebauthnApi, diff --git a/crates/webauthn/src/api/register/finish.rs b/crates/webauthn/src/api/register/finish.rs index 534c7f7d..d46d9b32 100644 --- a/crates/webauthn/src/api/register/finish.rs +++ b/crates/webauthn/src/api/register/finish.rs @@ -23,7 +23,7 @@ use chrono::Utc; use tracing::debug; use validator::Validate; -use openstack_keystone_core::api::KeystoneApiError; +use openstack_keystone_api_types::error::KeystoneApiError; use openstack_keystone_core::api::auth::Auth; use openstack_keystone_core::identity::IdentityApi; diff --git a/tests/federation/src/dex.rs b/tests/federation/src/dex.rs index 689f69de..2e895cef 100644 --- a/tests/federation/src/dex.rs +++ b/tests/federation/src/dex.rs @@ -23,7 +23,7 @@ use tokio_util::sync::CancellationToken; use tracing::debug; use tracing_test::traced_test; -use openstack_keystone_api_types::federation::{identity_provider::*, mapping::*}; +use openstack_keystone_api_types::federation::*; mod keystone_utils; diff --git a/tests/federation/src/github.rs b/tests/federation/src/github.rs index 9239ee3c..596f36a3 100644 --- a/tests/federation/src/github.rs +++ b/tests/federation/src/github.rs @@ -19,7 +19,7 @@ use serde_json::json; use std::env; use tracing_test::traced_test; -use openstack_keystone_api_types::federation::{identity_provider::*, mapping::*}; +use openstack_keystone_api_types::federation::*; use openstack_keystone_api_types::v4::user::*; mod keystone_utils; diff --git a/tests/federation/src/keycloak.rs b/tests/federation/src/keycloak.rs index 3dd67dd9..f0bc4ac4 100644 --- a/tests/federation/src/keycloak.rs +++ b/tests/federation/src/keycloak.rs @@ -25,7 +25,7 @@ use tracing::{debug, info}; use tracing_test::traced_test; use uuid::Uuid; -use openstack_keystone_api_types::federation::{identity_provider::*, mapping::*}; +use openstack_keystone_api_types::federation::*; mod keystone_utils; mod keycloak { diff --git a/tests/federation/src/keystone_utils.rs b/tests/federation/src/keystone_utils.rs index aa4bf36b..19f209d9 100644 --- a/tests/federation/src/keystone_utils.rs +++ b/tests/federation/src/keystone_utils.rs @@ -33,7 +33,7 @@ use std::time::Duration; use tokio::net::TcpListener; use tokio_util::sync::CancellationToken; -use openstack_keystone_api_types::federation::{auth::*, identity_provider::*, mapping::*}; +use openstack_keystone_api_types::federation::*; use openstack_keystone_api_types::v4::auth::token::TokenResponse; use openstack_keystone_api_types::v4::user::*; diff --git a/tests/integration/Cargo.toml b/tests/integration/Cargo.toml index 106e1476..2ac98a53 100644 --- a/tests/integration/Cargo.toml +++ b/tests/integration/Cargo.toml @@ -17,6 +17,7 @@ openstack-keystone-appcred-sql = { version = "0.1", path = "../../crates/appcred openstack-keystone-assignment-sql = { version = "0.1", path = "../../crates/assignment-sql/" } openstack-keystone-config = { version = "0.1", path = "../../crates/config" } openstack-keystone-core = { version = "0.1", path = "../../crates/core", features = ["mock"] } +openstack-keystone-core-types = { version = "0.1", path = "../../crates/core-types" } openstack-keystone-federation-sql = { version = "0.1", path = "../../crates/federation-sql/" } openstack-keystone-identity-sql = { version = "0.1", path = "../../crates/identity-sql/" } openstack-keystone-k8s-auth-sql = { version = "0.1", path = "../../crates/k8s-auth-sql/" } diff --git a/tests/integration/src/application_credential.rs b/tests/integration/src/application_credential.rs index 89d7bd0e..36d77be6 100644 --- a/tests/integration/src/application_credential.rs +++ b/tests/integration/src/application_credential.rs @@ -18,13 +18,13 @@ use std::sync::Arc; use uuid::Uuid; use openstack_keystone::application_credential::ApplicationCredentialApi; -use openstack_keystone::application_credential::types; use openstack_keystone::plugin_manager::PluginManager; use openstack_keystone_config::Config; use openstack_keystone_core::keystone::Service; use openstack_keystone_core::policy::MockPolicy; use openstack_keystone_core::provider::Provider; -use openstack_keystone_core::role::types as role_types; +use openstack_keystone_core_types::application_credential as types; +use openstack_keystone_core_types::role as role_types; use openstack_keystone_resource_sql::entity::{prelude::Project, project}; mod create; diff --git a/tests/integration/src/application_credential/create.rs b/tests/integration/src/application_credential/create.rs index bf2354eb..34040991 100644 --- a/tests/integration/src/application_credential/create.rs +++ b/tests/integration/src/application_credential/create.rs @@ -19,11 +19,11 @@ use secrecy::ExposeSecret; use tracing_test::traced_test; use uuid::Uuid; -use openstack_keystone::application_credential::types::*; use openstack_keystone::application_credential::{ ApplicationCredentialApi, ApplicationCredentialProviderError, }; -use openstack_keystone::role::types::*; +use openstack_keystone_core_types::application_credential::*; +use openstack_keystone_core_types::role::*; use super::get_state; diff --git a/tests/integration/src/application_credential/get.rs b/tests/integration/src/application_credential/get.rs index 19c35b1f..04dbf0cf 100644 --- a/tests/integration/src/application_credential/get.rs +++ b/tests/integration/src/application_credential/get.rs @@ -19,8 +19,8 @@ use tracing_test::traced_test; use uuid::Uuid; use openstack_keystone::application_credential::ApplicationCredentialApi; -use openstack_keystone::application_credential::types::*; -use openstack_keystone::role::types::RoleRef; +use openstack_keystone_core_types::application_credential::*; +use openstack_keystone_core_types::role::RoleRef; use super::get_state; diff --git a/tests/integration/src/application_credential/list.rs b/tests/integration/src/application_credential/list.rs index 9411c5f7..a3b9a9c6 100644 --- a/tests/integration/src/application_credential/list.rs +++ b/tests/integration/src/application_credential/list.rs @@ -18,7 +18,7 @@ use tracing_test::traced_test; use uuid::Uuid; use openstack_keystone::application_credential::ApplicationCredentialApi; -use openstack_keystone::application_credential::types::*; +use openstack_keystone_core_types::application_credential::*; use super::{create_ac, get_state}; diff --git a/tests/integration/src/assignment.rs b/tests/integration/src/assignment.rs index b4835fed..6a1bf2ca 100644 --- a/tests/integration/src/assignment.rs +++ b/tests/integration/src/assignment.rs @@ -14,8 +14,9 @@ use eyre::Result; use std::sync::Arc; -use openstack_keystone::assignment::{AssignmentApi, types::*}; +use openstack_keystone::assignment::AssignmentApi; use openstack_keystone::keystone::Service; +use openstack_keystone_core_types::assignment::*; mod grant; diff --git a/tests/integration/src/assignment/grant/list.rs b/tests/integration/src/assignment/grant/list.rs index 497f9dae..1d9ca3fd 100644 --- a/tests/integration/src/assignment/grant/list.rs +++ b/tests/integration/src/assignment/grant/list.rs @@ -17,9 +17,10 @@ use eyre::Result; use std::collections::BTreeSet; use tracing_test::traced_test; -use openstack_keystone::assignment::{AssignmentApi, types::*}; +use openstack_keystone::assignment::AssignmentApi; use openstack_keystone::identity::IdentityApi; use openstack_keystone::keystone::ServiceState; +use openstack_keystone_core_types::assignment::*; use super::get_state; use crate::common::{create_group, create_role, create_user}; diff --git a/tests/integration/src/assignment/grant/revoke.rs b/tests/integration/src/assignment/grant/revoke.rs index 803a621a..2eb49a02 100644 --- a/tests/integration/src/assignment/grant/revoke.rs +++ b/tests/integration/src/assignment/grant/revoke.rs @@ -19,13 +19,15 @@ use std::ops::Deref; use tracing_test::traced_test; use uuid::Uuid; -use openstack_keystone::application_credential::{ApplicationCredentialApi, types::*}; -use openstack_keystone::assignment::{AssignmentApi, types::*}; +use openstack_keystone::application_credential::ApplicationCredentialApi; +use openstack_keystone::assignment::AssignmentApi; use openstack_keystone::auth::*; -use openstack_keystone::identity::types::*; -use openstack_keystone::resource::types::*; -use openstack_keystone::role::types::*; use openstack_keystone::token::{TokenApi, TokenProviderError}; +use openstack_keystone_core_types::application_credential::*; +use openstack_keystone_core_types::assignment::*; +use openstack_keystone_core_types::identity::*; +use openstack_keystone_core_types::resource::*; +use openstack_keystone_core_types::role::*; use crate::assignment::{check_grant, grant_role_to_user_on_project}; use crate::common::get_state; diff --git a/tests/integration/src/common.rs b/tests/integration/src/common.rs index 4431e2dd..450cfccb 100644 --- a/tests/integration/src/common.rs +++ b/tests/integration/src/common.rs @@ -26,14 +26,16 @@ use sea_orm::{ use tempfile::TempDir; use uuid::Uuid; -use openstack_keystone::identity::{IdentityApi, types::*}; +use openstack_keystone::identity::IdentityApi; use openstack_keystone::plugin_manager::PluginManager; use openstack_keystone_appcred_sql::entity::prelude::*; use openstack_keystone_config::Config; use openstack_keystone_core::keystone::Service; use openstack_keystone_core::policy::MockPolicy; use openstack_keystone_core::provider::Provider; -use openstack_keystone_core::role::{RoleApi, types::RoleCreate}; +use openstack_keystone_core::role::RoleApi; +use openstack_keystone_core_types::identity::*; +use openstack_keystone_core_types::role::RoleCreate; use openstack_keystone_federation_sql::entity::prelude::*; use openstack_keystone_identity_sql::entity::{local_user, prelude::*, user}; use openstack_keystone_k8s_auth_sql::entity::prelude::*; diff --git a/tests/integration/src/identity.rs b/tests/integration/src/identity.rs index ff0dcd1c..5b7afbb4 100644 --- a/tests/integration/src/identity.rs +++ b/tests/integration/src/identity.rs @@ -17,9 +17,10 @@ use std::sync::Arc; use eyre::Result; -use openstack_keystone::identity::{IdentityApi, types::*}; +use openstack_keystone::identity::IdentityApi; use openstack_keystone::keystone::Service; use openstack_keystone::keystone::ServiceState; +use openstack_keystone_core_types::identity::*; use crate::common::*; use crate::impl_deleter; diff --git a/tests/integration/src/identity/service_account/create.rs b/tests/integration/src/identity/service_account/create.rs index bdbb0c16..d85635e1 100644 --- a/tests/integration/src/identity/service_account/create.rs +++ b/tests/integration/src/identity/service_account/create.rs @@ -17,7 +17,8 @@ use eyre::Result; use tracing_test::traced_test; use uuid::Uuid; -use openstack_keystone::identity::{IdentityApi, types::*}; +use openstack_keystone::identity::IdentityApi; +use openstack_keystone_core_types::identity::*; use super::*; diff --git a/tests/integration/src/identity/service_account/get.rs b/tests/integration/src/identity/service_account/get.rs index cd77ba27..7f44f8e9 100644 --- a/tests/integration/src/identity/service_account/get.rs +++ b/tests/integration/src/identity/service_account/get.rs @@ -17,7 +17,8 @@ use eyre::Result; use tracing_test::traced_test; use uuid::Uuid; -use openstack_keystone::identity::{IdentityApi, types::*}; +use openstack_keystone::identity::IdentityApi; +use openstack_keystone_core_types::identity::*; use super::*; diff --git a/tests/integration/src/identity/user/create.rs b/tests/integration/src/identity/user/create.rs index 945f4df0..601247a6 100644 --- a/tests/integration/src/identity/user/create.rs +++ b/tests/integration/src/identity/user/create.rs @@ -17,7 +17,8 @@ use eyre::Result; use tracing_test::traced_test; use uuid::Uuid; -use openstack_keystone::identity::{IdentityApi, types::*}; +use openstack_keystone::identity::IdentityApi; +use openstack_keystone_core_types::identity::*; use super::*; diff --git a/tests/integration/src/identity/user/get.rs b/tests/integration/src/identity/user/get.rs index c9527799..109c6552 100644 --- a/tests/integration/src/identity/user/get.rs +++ b/tests/integration/src/identity/user/get.rs @@ -17,7 +17,8 @@ use eyre::Result; use tracing_test::traced_test; use uuid::Uuid; -use openstack_keystone::identity::{IdentityApi, types::*}; +use openstack_keystone::identity::IdentityApi; +use openstack_keystone_core_types::identity::*; use super::*; diff --git a/tests/integration/src/identity/user/list.rs b/tests/integration/src/identity/user/list.rs index 1db3a00e..d92f0719 100644 --- a/tests/integration/src/identity/user/list.rs +++ b/tests/integration/src/identity/user/list.rs @@ -17,7 +17,8 @@ use eyre::Result; use tracing_test::traced_test; use uuid::Uuid; -use openstack_keystone::identity::{IdentityApi, types::*}; +use openstack_keystone::identity::IdentityApi; +use openstack_keystone_core_types::identity::*; use super::*; diff --git a/tests/integration/src/identity/user_group.rs b/tests/integration/src/identity/user_group.rs index 2306dc8f..c11d740d 100644 --- a/tests/integration/src/identity/user_group.rs +++ b/tests/integration/src/identity/user_group.rs @@ -25,9 +25,9 @@ use openstack_keystone_resource_sql::entity::project; use openstack_keystone::plugin_manager::PluginManager; use openstack_keystone_core::identity::IdentityApi; -use openstack_keystone_core::identity::types::*; use openstack_keystone_core::keystone::{Service, ServiceState}; use openstack_keystone_core::provider::Provider; +use openstack_keystone_core_types::identity::*; use crate::common::{bootstrap, get_isolated_database}; diff --git a/tests/integration/src/k8s_auth/instance.rs b/tests/integration/src/k8s_auth/instance.rs index a5a1aaf8..d7edd86e 100644 --- a/tests/integration/src/k8s_auth/instance.rs +++ b/tests/integration/src/k8s_auth/instance.rs @@ -17,9 +17,10 @@ use std::sync::Arc; use eyre::Result; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; use openstack_keystone::keystone::Service; use openstack_keystone::keystone::ServiceState; +use openstack_keystone_core_types::k8s_auth::*; mod create; mod delete; diff --git a/tests/integration/src/k8s_auth/instance/create.rs b/tests/integration/src/k8s_auth/instance/create.rs index fe0a7dc7..d7a0debc 100644 --- a/tests/integration/src/k8s_auth/instance/create.rs +++ b/tests/integration/src/k8s_auth/instance/create.rs @@ -16,7 +16,8 @@ use eyre::Result; use tracing_test::traced_test; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; +use openstack_keystone_core_types::k8s_auth::*; use super::super::get_state; diff --git a/tests/integration/src/k8s_auth/instance/delete.rs b/tests/integration/src/k8s_auth/instance/delete.rs index b87a52f3..a96cb67f 100644 --- a/tests/integration/src/k8s_auth/instance/delete.rs +++ b/tests/integration/src/k8s_auth/instance/delete.rs @@ -16,7 +16,8 @@ use eyre::Result; use tracing_test::traced_test; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; +use openstack_keystone_core_types::k8s_auth::*; use super::super::get_state; diff --git a/tests/integration/src/k8s_auth/instance/get.rs b/tests/integration/src/k8s_auth/instance/get.rs index 8c99be0f..3844ead6 100644 --- a/tests/integration/src/k8s_auth/instance/get.rs +++ b/tests/integration/src/k8s_auth/instance/get.rs @@ -16,7 +16,8 @@ use eyre::Result; use tracing_test::traced_test; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; +use openstack_keystone_core_types::k8s_auth::*; use super::super::get_state; use super::create_k8s_auth_instance; diff --git a/tests/integration/src/k8s_auth/instance/list.rs b/tests/integration/src/k8s_auth/instance/list.rs index e9c3d9c1..5d1d585f 100644 --- a/tests/integration/src/k8s_auth/instance/list.rs +++ b/tests/integration/src/k8s_auth/instance/list.rs @@ -16,7 +16,8 @@ use eyre::Result; use tracing_test::traced_test; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; +use openstack_keystone_core_types::k8s_auth::*; use super::super::get_state; use super::create_k8s_auth_instance; diff --git a/tests/integration/src/k8s_auth/instance/update.rs b/tests/integration/src/k8s_auth/instance/update.rs index 2c860f6d..7bfa8a8c 100644 --- a/tests/integration/src/k8s_auth/instance/update.rs +++ b/tests/integration/src/k8s_auth/instance/update.rs @@ -16,7 +16,8 @@ use eyre::Result; use tracing_test::traced_test; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; +use openstack_keystone_core_types::k8s_auth::*; use super::super::get_state; use super::create_k8s_auth_instance; diff --git a/tests/integration/src/k8s_auth/role.rs b/tests/integration/src/k8s_auth/role.rs index e2b97a61..401d854b 100644 --- a/tests/integration/src/k8s_auth/role.rs +++ b/tests/integration/src/k8s_auth/role.rs @@ -17,9 +17,10 @@ use std::sync::Arc; use eyre::Result; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; use openstack_keystone::keystone::Service; use openstack_keystone::keystone::ServiceState; +use openstack_keystone_core_types::k8s_auth::*; mod create; mod delete; diff --git a/tests/integration/src/k8s_auth/role/create.rs b/tests/integration/src/k8s_auth/role/create.rs index 34e9a86f..1c8cae78 100644 --- a/tests/integration/src/k8s_auth/role/create.rs +++ b/tests/integration/src/k8s_auth/role/create.rs @@ -16,7 +16,8 @@ use eyre::Result; use tracing_test::traced_test; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; +use openstack_keystone_core_types::k8s_auth::*; use super::super::get_state; use super::super::instance::create_k8s_auth_instance; diff --git a/tests/integration/src/k8s_auth/role/delete.rs b/tests/integration/src/k8s_auth/role/delete.rs index c1f7d2e3..7cd08021 100644 --- a/tests/integration/src/k8s_auth/role/delete.rs +++ b/tests/integration/src/k8s_auth/role/delete.rs @@ -16,7 +16,8 @@ use eyre::Result; use tracing_test::traced_test; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; +use openstack_keystone_core_types::k8s_auth::*; use super::super::get_state; use super::super::instance::create_k8s_auth_instance; diff --git a/tests/integration/src/k8s_auth/role/get.rs b/tests/integration/src/k8s_auth/role/get.rs index 45021a7f..51f75f1e 100644 --- a/tests/integration/src/k8s_auth/role/get.rs +++ b/tests/integration/src/k8s_auth/role/get.rs @@ -16,7 +16,8 @@ use eyre::Result; use tracing_test::traced_test; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; +use openstack_keystone_core_types::k8s_auth::*; use super::super::get_state; use super::super::instance::create_k8s_auth_instance; diff --git a/tests/integration/src/k8s_auth/role/list.rs b/tests/integration/src/k8s_auth/role/list.rs index fa55637c..7f430bb3 100644 --- a/tests/integration/src/k8s_auth/role/list.rs +++ b/tests/integration/src/k8s_auth/role/list.rs @@ -16,7 +16,8 @@ use eyre::Result; use tracing_test::traced_test; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; +use openstack_keystone_core_types::k8s_auth::*; use super::super::get_state; use super::super::instance::create_k8s_auth_instance; diff --git a/tests/integration/src/k8s_auth/role/update.rs b/tests/integration/src/k8s_auth/role/update.rs index afec5b7c..0b5073bc 100644 --- a/tests/integration/src/k8s_auth/role/update.rs +++ b/tests/integration/src/k8s_auth/role/update.rs @@ -16,7 +16,8 @@ use eyre::Result; use tracing_test::traced_test; -use openstack_keystone::k8s_auth::{K8sAuthApi, types::*}; +use openstack_keystone::k8s_auth::K8sAuthApi; +use openstack_keystone_core_types::k8s_auth::*; use super::super::get_state; use super::super::instance::create_k8s_auth_instance; diff --git a/tests/integration/src/resource.rs b/tests/integration/src/resource.rs index 7d44640a..da395174 100644 --- a/tests/integration/src/resource.rs +++ b/tests/integration/src/resource.rs @@ -19,7 +19,8 @@ use eyre::Result; use openstack_keystone::keystone::Service; use openstack_keystone::keystone::ServiceState; -use openstack_keystone::resource::{ResourceApi, types::*}; +use openstack_keystone::resource::ResourceApi; +use openstack_keystone_core_types::resource::*; use crate::common::*; use crate::impl_deleter; diff --git a/tests/integration/src/revoke.rs b/tests/integration/src/revoke.rs index a96d2271..ac0483c4 100644 --- a/tests/integration/src/revoke.rs +++ b/tests/integration/src/revoke.rs @@ -18,11 +18,12 @@ use tracing_test::traced_test; use uuid::Uuid; use openstack_keystone::auth::*; -use openstack_keystone::identity::types::*; -use openstack_keystone::resource::types::*; use openstack_keystone::revoke::RevokeApi; -use openstack_keystone::role::types::RoleCreateBuilder; use openstack_keystone::token::TokenApi; +use openstack_keystone_core_types::identity::*; +use openstack_keystone_core_types::resource::*; +use openstack_keystone_core_types::revoke::*; +use openstack_keystone_core_types::role::RoleCreateBuilder; use crate::assignment::grant_role_to_user_on_project; use crate::common::get_state; @@ -186,7 +187,7 @@ async fn test_revoked_event_role() -> Result<(), Report> { .get_revoke_provider() .create_revocation_event( &state, - openstack_keystone::revoke::RevocationEventCreateBuilder::default() + RevocationEventCreateBuilder::default() .role_id(role.id.clone()) .revoked_at(Utc::now()) .issued_before(Utc::now()) @@ -277,7 +278,7 @@ async fn test_revoked_event_user() -> Result<(), Report> { .get_revoke_provider() .create_revocation_event( &state, - openstack_keystone::revoke::RevocationEventCreateBuilder::default() + RevocationEventCreateBuilder::default() .user_id(user.id.clone()) .revoked_at(Utc::now()) .issued_before(Utc::now()) @@ -368,7 +369,7 @@ async fn test_revoked_event_project() -> Result<(), Report> { .get_revoke_provider() .create_revocation_event( &state, - openstack_keystone::revoke::RevocationEventCreateBuilder::default() + RevocationEventCreateBuilder::default() .project_id(project.id.clone()) .revoked_at(Utc::now()) .issued_before(Utc::now()) diff --git a/tests/integration/src/role.rs b/tests/integration/src/role.rs index 7e040785..ba307815 100644 --- a/tests/integration/src/role.rs +++ b/tests/integration/src/role.rs @@ -19,7 +19,8 @@ use eyre::Result; use openstack_keystone::keystone::Service; use openstack_keystone::keystone::ServiceState; -use openstack_keystone::role::{RoleApi, types::*}; +use openstack_keystone::role::RoleApi; +use openstack_keystone_core_types::role::*; use crate::common::*; use crate::impl_deleter; diff --git a/tests/integration/src/role/create.rs b/tests/integration/src/role/create.rs index 14c26cc2..4c35850b 100644 --- a/tests/integration/src/role/create.rs +++ b/tests/integration/src/role/create.rs @@ -16,7 +16,8 @@ use eyre::Result; use uuid::Uuid; -use openstack_keystone::role::{RoleApi, types::*}; +use openstack_keystone::role::RoleApi; +use openstack_keystone_core_types::role::*; use crate::common::get_state; diff --git a/tests/integration/src/role/list.rs b/tests/integration/src/role/list.rs index 78a1003a..016787ea 100644 --- a/tests/integration/src/role/list.rs +++ b/tests/integration/src/role/list.rs @@ -17,7 +17,8 @@ use eyre::Result; use std::collections::BTreeSet; use openstack_keystone::keystone::ServiceState; -use openstack_keystone::role::{RoleApi, types::*}; +use openstack_keystone::role::RoleApi; +use openstack_keystone_core_types::role::*; use crate::common::create_role; use crate::common::get_state; diff --git a/tests/integration/src/token/token_restriction.rs b/tests/integration/src/token/token_restriction.rs index 05efe19a..fa54a8fb 100644 --- a/tests/integration/src/token/token_restriction.rs +++ b/tests/integration/src/token/token_restriction.rs @@ -19,7 +19,8 @@ use eyre::Result; use openstack_keystone::keystone::Service; use openstack_keystone::keystone::ServiceState; -use openstack_keystone::token::{TokenApi, types::*}; +use openstack_keystone::token::TokenApi; +use openstack_keystone_core_types::token::*; use crate::common::*; use crate::impl_deleter; diff --git a/tests/integration/src/token/validate.rs b/tests/integration/src/token/validate.rs index e525346e..163452c6 100644 --- a/tests/integration/src/token/validate.rs +++ b/tests/integration/src/token/validate.rs @@ -20,11 +20,13 @@ use tempfile::TempDir; use openstack_keystone::plugin_manager::PluginManager; use openstack_keystone_config::Config; -use openstack_keystone_core::assignment::{AssignmentApi, types::AssignmentCreate}; -use openstack_keystone_core::identity::{IdentityApi, types::*}; +use openstack_keystone_core::assignment::AssignmentApi; +use openstack_keystone_core::identity::IdentityApi; use openstack_keystone_core::keystone::Service; use openstack_keystone_core::policy::MockPolicy; use openstack_keystone_core::provider::Provider; +use openstack_keystone_core_types::assignment::AssignmentCreate; +use openstack_keystone_core_types::identity::*; use openstack_keystone_resource_sql::entity::{prelude::Project, project}; mod application_credential; diff --git a/tests/integration/src/token/validate/application_credential.rs b/tests/integration/src/token/validate/application_credential.rs index 255d714b..cab25228 100644 --- a/tests/integration/src/token/validate/application_credential.rs +++ b/tests/integration/src/token/validate/application_credential.rs @@ -21,11 +21,11 @@ use tracing_test::traced_test; use uuid::Uuid; use openstack_keystone::application_credential::ApplicationCredentialApi; -use openstack_keystone::application_credential::types::*; use openstack_keystone::auth::*; -use openstack_keystone::resource::types::ProjectBuilder; -use openstack_keystone::role::types::*; use openstack_keystone::token::{Token, TokenApi, TokenProviderError}; +use openstack_keystone_core_types::application_credential::*; +use openstack_keystone_core_types::resource::ProjectBuilder; +use openstack_keystone_core_types::role::*; use super::{create_user, get_state, grant_role_to_user_on_project}; use crate::common::create_role; diff --git a/tests/integration/src/token/validate/trust.rs b/tests/integration/src/token/validate/trust.rs index 622d3a17..bd82ad84 100644 --- a/tests/integration/src/token/validate/trust.rs +++ b/tests/integration/src/token/validate/trust.rs @@ -26,10 +26,11 @@ use openstack_keystone_trust_sql::entity::{ use openstack_keystone::auth::*; use openstack_keystone::keystone::Service; -use openstack_keystone::role::{RoleApi, types::RoleCreate}; +use openstack_keystone::role::RoleApi; use openstack_keystone::token::{Token, TokenApi, TokenProviderError}; use openstack_keystone::trust::TrustApi; -use openstack_keystone::trust::types::*; +use openstack_keystone_core_types::role::RoleCreate; +use openstack_keystone_core_types::trust::*; use super::{create_user, get_state, grant_role_to_user_on_project}; use crate::common::create_role; diff --git a/tools/Dockerfile.functest b/tools/Dockerfile.functest index ef81ef37..20908cda 100644 --- a/tools/Dockerfile.functest +++ b/tools/Dockerfile.functest @@ -14,6 +14,10 @@ RUN USER=root cargo new keystone WORKDIR /usr/src/keystone +RUN USER=root cargo new --name core --lib crates/core +RUN USER=root cargo new --name core-types --lib crates/core-types +RUN USER=root cargo new --name api-types --lib crates/api-types + RUN USER=root cargo new --name appcred-sql --lib crates/appcred-sql RUN USER=root cargo new --name assignment-sql --lib crates/assignment-sql RUN USER=root cargo new --name catalog-sql --lib crates/catalog-sql @@ -34,6 +38,7 @@ COPY crates/appcred-sql/Cargo.toml /usr/src/keystone/crates/appcred-sql/ COPY crates/assignment-sql/Cargo.toml /usr/src/keystone/crates/assignment-sql/ COPY crates/config/Cargo.toml /usr/src/keystone/crates/config/ COPY crates/core/Cargo.toml /usr/src/keystone/crates/core/ +COPY crates/core-types/Cargo.toml /usr/src/keystone/crates/core-types/ COPY crates/catalog-sql/Cargo.toml /usr/src/keystone/crates/catalog-sql/ COPY crates/federation-sql/Cargo.toml /usr/src/keystone/crates/federation-sql/ COPY crates/identity-sql/Cargo.toml /usr/src/keystone/crates/identity-sql/ @@ -57,10 +62,8 @@ RUN mkdir -p crates/keystone/src/bin && touch crates/keystone/src/lib.rs &&\ cp src/main.rs crates/keystone/src/bin/keystone_db.rs &&\ mkdir -p tests/loadtest/src &&\ cp src/main.rs tests/loadtest/src/main.rs &&\ - mkdir -p crates/api-types/src && touch crates/api-types/src/lib.rs &&\ mkdir -p crates/assignment-sql/src && touch crates/assignment-sql/src/lib.rs &&\ mkdir -p crates/config/src && touch crates/config/src/lib.rs &&\ - mkdir -p crates/core/src && touch crates/core/src/lib.rs &&\ mkdir -p crates/storage/src && touch crates/storage/src/lib.rs &&\ mkdir -p crates/token-fernet/src && touch crates/token-fernet/src/lib.rs &&\ mkdir -p crates/token-fernet/benches && touch crates/token-fernet/benches/fernet_token.rs &&\ @@ -69,6 +72,7 @@ RUN mkdir -p crates/keystone/src/bin && touch crates/keystone/src/lib.rs &&\ ## This is a dummy build to get the dependencies cached. RUN cargo build +COPY crates/core-types/ /usr/src/keystone/crates/core-types COPY crates/api-types/ /usr/src/keystone/crates/api-types COPY tests ./tests