From b8482324159114dd0ff2137c2b53c7eaa379148f Mon Sep 17 00:00:00 2001 From: Matt Pryor Date: Tue, 29 Oct 2024 12:15:20 +0000 Subject: [PATCH 1/5] Update docs packages + fix broken links --- docs/best-practice.md | 2 +- docs/configuration/03-kubernetes-config.md | 2 +- docs/deployment/automation.md | 2 +- docs/deployment/testing.md | 2 +- docs/developing/index.md | 2 +- docs/index.md | 2 +- docs/repository/index.md | 2 +- requirements-docs.txt | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/best-practice.md b/docs/best-practice.md index 167dd6e8..beb46109 100644 --- a/docs/best-practice.md +++ b/docs/best-practice.md @@ -102,7 +102,7 @@ environments. The `ansible-playbook` command should **never** be executed manual The recommended approach is to automatically deploy an independent `aio` environment for each feature branch, also known as -[per-branch dynamic review environments](deployment/automation/#per-branch-dynamic-review-environments). +[per-branch dynamic review environments](deployment/automation.md#per-branch-dynamic-review-environments). This allows changes to be validated before they are merged to `main`. Once a change is merged to `main`, it will be deployed automatically to the `staging` environment. diff --git a/docs/configuration/03-kubernetes-config.md b/docs/configuration/03-kubernetes-config.md index e8cca08d..73e460ef 100644 --- a/docs/configuration/03-kubernetes-config.md +++ b/docs/configuration/03-kubernetes-config.md @@ -95,7 +95,7 @@ to use volume-backed instances instead. !!! tip "etcd on a separate block device" If you only have a limited amount of SSD or, even better, local disk, available, - consider placing [etcd on a separate block device](#etcd-block-device) to make + consider placing [etcd on a separate block device](#etcd-configuration) to make best use of the limited capacity. To configure Kubernetes clusters to use volume-backed instances (i.e. use a Cinder diff --git a/docs/deployment/automation.md b/docs/deployment/automation.md index 88d41206..c8812a01 100644 --- a/docs/deployment/automation.md +++ b/docs/deployment/automation.md @@ -16,7 +16,7 @@ environments, although deployments to production typically include a manual appr !!! tip "Using a site mixin" To get the maximum benefit from automated deployments and the - [feature branch workflow](../repository/index.md#making-changes-to-your-environment), + [feature branch workflow](../repository/index.md#making-changes-to-your-configuration), you should try to minimise the differences between the production, staging and [dynamic review](#per-branch-dynamic-review-environments) environments. diff --git a/docs/deployment/testing.md b/docs/deployment/testing.md index 4082a3a3..7a214314 100644 --- a/docs/deployment/testing.md +++ b/docs/deployment/testing.md @@ -149,7 +149,7 @@ clouds: ## Generating and executing tests Before tests can be generated and executed for an [environment](../environments.md), the -environment must be successfully deployed either [manually](../) or by +environment must be successfully deployed either [manually](./index.md) or by [automation](./automation.md). You must also have the Python dependencies installed on the machine that the tests will be diff --git a/docs/developing/index.md b/docs/developing/index.md index 2a6de917..36ba7acc 100644 --- a/docs/developing/index.md +++ b/docs/developing/index.md @@ -16,7 +16,7 @@ conflict with or break things for others. Azimuth supports using a single [configuration environment](../environments.md) to deploy multiple independent Azimuth instances. When -[activating an environment](../deployment/#activating-an-environment), a unique instance name +[activating an environment](../deployment/index.md#activating-an-environment), a unique instance name can be given as a second argument to the `activate` script, e.g.: ```bash diff --git a/docs/index.md b/docs/index.md index 96a8ea42..466bd489 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,7 +11,7 @@ driven by configuration derived from the [azimuth-config reference configuration](https://github.com/azimuth-cloud/azimuth-config). The `azimuth-config` repository is designed to be forked for a specific site and is structured -into multiple [environments](#environments). This structure allows common configuration to be +into multiple [environments](./environments.md). This structure allows common configuration to be shared but overridden where required using composition of environments. To try out Azimuth on your OpenStack cloud, you can follow [these instructions](./try.md) diff --git a/docs/repository/index.md b/docs/repository/index.md index 947fd001..c20e689e 100644 --- a/docs/repository/index.md +++ b/docs/repository/index.md @@ -103,7 +103,7 @@ component versions, upgraded dependencies and new images. If you have automated deployments, which is recommended for a production installation, this process - [can also be automated](../deployment/automation.md#automated-synchronisation-of-upstream-changes). + [can also be automated](../deployment/automation.md#automated-upgrades). To upgrade your Azimuth configuration to a new release, use the following steps to create a new branch containing the upgrade: diff --git a/requirements-docs.txt b/requirements-docs.txt index a9c1f199..a9489709 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,3 +1,3 @@ -mkdocs==1.3.0 -mkdocs-material==8.3.8 +mkdocs==1.6.1 +mkdocs-material==9.5.42 mkdocs-git-revision-date-localized-plugin From 74776636ba494511cb369a2ae8b7bd3fd38be14b Mon Sep 17 00:00:00 2001 From: Matt Pryor Date: Tue, 29 Oct 2024 16:34:22 +0000 Subject: [PATCH 2/5] First pass at sequence diagram for Zenith auth --- docs/architecture/identity.md | 115 ++++++++++++++++++++++++++++++++++ docs/architecture/index.md | 3 + mkdocs.yml | 9 ++- 3 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 docs/architecture/identity.md create mode 100644 docs/architecture/index.md diff --git a/docs/architecture/identity.md b/docs/architecture/identity.md new file mode 100644 index 00000000..c5c9947e --- /dev/null +++ b/docs/architecture/identity.md @@ -0,0 +1,115 @@ +# Identity in Azimuth + +This document explains how identity is designed to work in Azimuth. + +## Personas + +Azimuth has two distinct personas that consume Azimuth and the platforms that are deployed +using it - **platform admins** and **platform users**. + +**Platform admins** are able to access the Azimuth portal where they can administer platforms +in their tenancies and the platform users that are able to access the services for those +platforms (e.g. Guacamole web desktops, monitoring dashboards). + +**Platform users** are able to access platform services to which they have been granted access +by a platform admin. They do not need to be able to sign in to the Azimuth portal or even be +aware that the platform is deployed in an Azimuth tenancy. + +By default, platform admins are also platform users that are authorised to access all of the +services for platforms deployed in their tenancies. + +## Technologies + +Azimuth utilises Kubernetes Ingress, Zenith and Keycloak to implement secure access to platform +services without consuming any public IP addresses. + +### Kubernetes Ingress + +Azimuth and Zenith leverage Kubernetes Ingress as a dynamically configurable HTTP(S) proxy to +route external traffic to the correct service based on the hostname and/or path. + +### Zenith + +Zenith is a tunnelling HTTP(S) proxy that is used by Azimuth to expose platform services. Using +Zenith allows Azimuth to expose platform services that are behind a NAT or firewall without +consuming public IPs. + +Zenith uses a server/client model where a client initiates a secure SSH tunnel with the server +for the service that wants to be proxied. The server then forwards traffic for the proxied service +back down the tunnel. This is accomplished by creating a Kubernetes `Service` for each Zenith +service and using Kubernetes Ingress to route traffic to the correct service based on the hostname. + +Zenith is able to perform TLS termination and single sign-on using OpenID Connect (OIDC) for +proxied services before forwarding traffic to them. This is implemented by configuring the +Kubernetes `Ingress` resources appropriately - in particular the OIDC authentication and +authorisation is implemented using an auth subrequest. + +### Keycloak + +As part of an Azimuth installation, a Keycloak instance is deployed. Azimuth uses this Keycloak +instance to provide authentication and authorisation for platform services exposed using Zenith. + +Azimuth manages a realm in Keycloak for each OpenStack project in which platforms are deployed. +By default, this realm has a single federation that allows users to sign in using their existing +Azimuth session. Users that sign in using this method are automatically added to an `admins` +group that allows them to administer the realm and grants access to all platform services. +Platform admins are able to create local users in this realm and add federations to other identity +sources e.g. Microsoft Entra, Google or LDAP. + +Within that realm, Azimuth then manages an OpenID Connect client for each platform service and +a group that is used to grant access to that service. Zenith is configured to use this OIDC +client and group when performing authentication and authorisation for the service. + +Platform admins can grant a platform user access to a platform service by adding them to the +group for that service. Keycloak has powerful features for automatically mapping users from +federated user sources into groups if desired. + +## Accessing platform services + +The following diagram shows the sequence of actions for a user accessing a platform service in +Azimuth. This diagram is the same regardless of how the user authenticates with Azimuth and +the mechanism for obtaining a cloud credential: + +```mermaid +sequenceDiagram + actor U as User + participant P as Proxy + participant R as Keycloak Realm + participant A as Azimuth Portal + participant S as Proxied Service + + U ->> P: Visit service URL + opt OIDC ID token cookie not present or ID token invalid + P -->> U: Redirect to OIDC authorize URL + U ->> R: Visit OIDC authorize URL + opt User does not have a current Keycloak session + R -->> U: Redirect to login page + U ->> R: Visit login page + alt User selects Azimuth IDP + R -->> U: Redirect to Azimuth Portal + U ->> A: Authenticate with Azimuth Portal + A ->> A: Verify user belongs to tenancy for realm + A -->> U: Redirect to Keycloak realm + U ->> R: Complete authentication + else User selects another authentication method + R ->> R: Authenticate user
This may redirect to an external IDP + end + end + R -->> U: Redirect to OIDC callback URL + U ->> P: Visit OIDC callback URL + P ->> R: Request OIDC ID token + R ->> P: Return OIDC ID token with groups claim + P -->> U: Redirect to service URL, setting OIDC ID token cookie + break + U -->> U: Return to start with
valid OIDC ID token cookie + end + end + P ->> P: Check groups claim of ID token for required groups + alt User is authorised + P ->> S: Forward request to proxied service + S ->> P: Response from proxied service + P ->> U: Return response to user + else User is not authorised + P ->> U: Return error page + end +``` diff --git a/docs/architecture/index.md b/docs/architecture/index.md new file mode 100644 index 00000000..218ae032 --- /dev/null +++ b/docs/architecture/index.md @@ -0,0 +1,3 @@ +# Azimuth Architecture + +Coming soon! diff --git a/mkdocs.yml b/mkdocs.yml index 98dcb8f2..7dc3d703 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -43,6 +43,9 @@ nav: - debugging/consul.md - debugging/kubernetes.md - debugging/caas.md + - Architecture: + - architecture/index.md + - architecture/identity.md - Developing: - developing/index.md @@ -67,7 +70,11 @@ markdown_extensions: anchor_linenums: true - pymdownx.inlinehilite - pymdownx.snippets - - pymdownx.superfences + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format - toc: toc_depth: 3 From 2651bb0ca42414f0b81034c062d0e7ee6fe6225a Mon Sep 17 00:00:00 2001 From: Matt Pryor Date: Tue, 29 Oct 2024 16:35:44 +0000 Subject: [PATCH 3/5] Fix formatting --- docs/architecture/identity.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture/identity.md b/docs/architecture/identity.md index c5c9947e..351a0eec 100644 --- a/docs/architecture/identity.md +++ b/docs/architecture/identity.md @@ -88,7 +88,7 @@ sequenceDiagram alt User selects Azimuth IDP R -->> U: Redirect to Azimuth Portal U ->> A: Authenticate with Azimuth Portal - A ->> A: Verify user belongs to tenancy for realm + A ->> A: Verify user belongs
to tenancy for realm A -->> U: Redirect to Keycloak realm U ->> R: Complete authentication else User selects another authentication method From 3950153867f6e22ebe4e20354517f1d688da6cc6 Mon Sep 17 00:00:00 2001 From: Matt Pryor Date: Thu, 31 Oct 2024 15:05:06 +0000 Subject: [PATCH 4/5] Add section on Azimuth authentication --- docs/architecture/identity.md | 111 +++++++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 22 deletions(-) diff --git a/docs/architecture/identity.md b/docs/architecture/identity.md index 351a0eec..85ccd19f 100644 --- a/docs/architecture/identity.md +++ b/docs/architecture/identity.md @@ -9,7 +9,7 @@ using it - **platform admins** and **platform users**. **Platform admins** are able to access the Azimuth portal where they can administer platforms in their tenancies and the platform users that are able to access the services for those -platforms (e.g. Guacamole web desktops, monitoring dashboards). +platforms (e.g. Jupyter Notebooks, Guacamole web desktops, monitoring dashboards). **Platform users** are able to access platform services to which they have been granted access by a platform admin. They do not need to be able to sign in to the Azimuth portal or even be @@ -20,8 +20,8 @@ services for platforms deployed in their tenancies. ## Technologies -Azimuth utilises Kubernetes Ingress, Zenith and Keycloak to implement secure access to platform -services without consuming any public IP addresses. +Azimuth utilises Kubernetes Ingress, Zenith and Keycloak to implement secure access to Azimuth +and the platforms deployed using it. ### Kubernetes Ingress @@ -47,28 +47,97 @@ authorisation is implemented using an auth subrequest. ### Keycloak As part of an Azimuth installation, a Keycloak instance is deployed. Azimuth uses this Keycloak -instance to provide authentication and authorisation for platform services exposed using Zenith. +instance to provide authentication and authorisation for platform services exposed using Zenith, +and optionally for Azimuth itself. -Azimuth manages a realm in Keycloak for each OpenStack project in which platforms are deployed. -By default, this realm has a single federation that allows users to sign in using their existing -Azimuth session. Users that sign in using this method are automatically added to an `admins` -group that allows them to administer the realm and grants access to all platform services. -Platform admins are able to create local users in this realm and add federations to other identity -sources e.g. Microsoft Entra, Google or LDAP. +## Accessing Azimuth -Within that realm, Azimuth then manages an OpenID Connect client for each platform service and +Azimuth allows an Azimuth operator to configure authentication and authorization for Azimuth +itself using either OpenStack credentials directly or using a Keycloak realm to manage users. + +An "Azimuth tenancy" is essentially a `Namespace` in the Azimuth Kubernetes cluster that holds +the platform definitions and related resources for that tenancy (implemented as Kubernetes custom +resources). Currently, these tenancies have a one-to-one mapping with OpenStack projects. + +In order to manage platform resources in the underlying cloud on behalf of users, Azimuth needs +to be able to translate an authenticated Azimuth session into two things: + + 1. A list of Azimuth tenancies that a user is permitted to access + 2. A credential that is able to manage resources in the corresponding OpenStack project + +This section documents how this is acheived for each authentication method. + +### Using OpenStack credentials + +Azimuth allows authenticating directly using credentials for the underlying OpenStack cloud, +with support for domain/username/password, application credentials and federated identity +providers configured in Keystone. + +In each case, Azimuth obtains a token that can be used to interact with the OpenStack APIs on +behalf of the user. This token is _unscoped_, i.e. not associated with a specific OpenStack +project, but can be used to query the OpenStack projects that the user has access to (and hence +the Azimuth tenancies). Once the user enters a tenancy context in Azimuth, the unscoped token +can be exchanged for a _project-scoped_ token that allows Azimuth to manage resources in the +OpenStack project. + +```mermaid +sequenceDiagram + actor U as User + participant A as Azimuth Portal + participant N as Azimuth Tenant
Namespace + participant O as OpenStack + + U ->> A: List machines in tenancy X + opt Session cookie not present or unscoped token expired + A -->> U: Redirect to login page + U ->>+ A: Visit login page + A ->>- U: List of authentication methods + alt Domain/username/password or application credential selected + U ->>+ A: Supply credentials + A ->>+ O: Request unscoped token using supplied credentials + O ->>- A: Return unscoped token for user + A -->>- U: Redirect to list machines
Set cookie containing unscoped token + else Keystone federated IDP selected + U ->>+ A: Keystone federated IDP selected + A -->>- U: Redirect user to Keystone federation URL + U ->>+ O: Visit Keystone federation URL + O ->> O: Authenticate user with external IDP
May require additional redirects, e.g. for OIDC + O ->>- U: Return unscoped token to user's browser + U ->>+ A: Complete authentication by POSTing unscoped token + A -->>- U: Redirect to list machines
Set cookie containing unscoped token + end + end + A ->>+ O: Exchange unscoped token for scoped token for project X + O ->>- A: Return scoped token for project X + A ->>+ O: List servers in project X + O ->>- A: List of servers in project X + A ->> U: List of machines in tenancy X +``` + +## Accessing platform services + +Access to platform services in Azimuth is mediated using Keycloak, regardless of how the user +authenticates with Azimuth and the mechanism for obtaining a cloud credential. + +Azimuth manages a realm in Keycloak for each Azimuth tenancy, and the platform users for a +tenancy are users that exist in the associated Keycloak realm. These users can be local Keycloak +users or users from a federated identity provider such as Microsoft Entra, Google or LDAP. + +By default, this realm has a single federated IDP that allows users belonging to the tenancy to +sign in using their existing Azimuth session (i.e. platform admins). Users that sign in using +this method are automatically added to an `admins` group that allows them to administer the realm +and grants access to all platform services for the tenancy. Platform admins are able to manage +local users and federated identity providers in this realm as required for their needs. + +Within this realm, Azimuth then manages an OpenID Connect client for each platform service and a group that is used to grant access to that service. Zenith is configured to use this OIDC client and group when performing authentication and authorisation for the service. Platform admins can grant a platform user access to a platform service by adding them to the group for that service. Keycloak has powerful features for automatically mapping users from -federated user sources into groups if desired. +federated identity providers into groups if desired. -## Accessing platform services - -The following diagram shows the sequence of actions for a user accessing a platform service in -Azimuth. This diagram is the same regardless of how the user authenticates with Azimuth and -the mechanism for obtaining a cloud credential: +The following diagram shows the sequence of actions for a user accessing a platform service: ```mermaid sequenceDiagram @@ -76,10 +145,10 @@ sequenceDiagram participant P as Proxy participant R as Keycloak Realm participant A as Azimuth Portal - participant S as Proxied Service + participant S as Platform Service U ->> P: Visit service URL - opt OIDC ID token cookie not present or ID token invalid + opt OIDC ID token cookie not present or ID token invalid or expired P -->> U: Redirect to OIDC authorize URL U ->> R: Visit OIDC authorize URL opt User does not have a current Keycloak session @@ -100,9 +169,7 @@ sequenceDiagram P ->> R: Request OIDC ID token R ->> P: Return OIDC ID token with groups claim P -->> U: Redirect to service URL, setting OIDC ID token cookie - break - U -->> U: Return to start with
valid OIDC ID token cookie - end + U ->> P: Visit service URL with valid OIDC ID token cookie end P ->> P: Check groups claim of ID token for required groups alt User is authorised From ed397d75357c1d480e5b83c9d009588bb8bc9bcc Mon Sep 17 00:00:00 2001 From: Matt Pryor Date: Mon, 4 Nov 2024 14:25:08 +0000 Subject: [PATCH 5/5] Add sequence diagram for OIDC flow --- docs/architecture/identity.md | 182 +++++++++++++++++++++++++++------- 1 file changed, 146 insertions(+), 36 deletions(-) diff --git a/docs/architecture/identity.md b/docs/architecture/identity.md index 85ccd19f..eb525a9e 100644 --- a/docs/architecture/identity.md +++ b/docs/architecture/identity.md @@ -20,13 +20,19 @@ services for platforms deployed in their tenancies. ## Technologies -Azimuth utilises Kubernetes Ingress, Zenith and Keycloak to implement secure access to Azimuth +Azimuth utilises Kubernetes Ingress, Keycloak and Zenith to implement secure access to Azimuth and the platforms deployed using it. ### Kubernetes Ingress Azimuth and Zenith leverage Kubernetes Ingress as a dynamically configurable HTTP(S) proxy to -route external traffic to the correct service based on the hostname and/or path. +route external traffic to the correct Kubernetes service based on the hostname and/or path. + +### Keycloak + +As part of an Azimuth installation, a Keycloak instance is deployed. Azimuth uses this Keycloak +instance to provide authentication and authorisation for platform services exposed using Zenith, +and optionally for Azimuth itself. ### Zenith @@ -44,16 +50,11 @@ proxied services before forwarding traffic to them. This is implemented by confi Kubernetes `Ingress` resources appropriately - in particular the OIDC authentication and authorisation is implemented using an auth subrequest. -### Keycloak - -As part of an Azimuth installation, a Keycloak instance is deployed. Azimuth uses this Keycloak -instance to provide authentication and authorisation for platform services exposed using Zenith, -and optionally for Azimuth itself. - ## Accessing Azimuth -Azimuth allows an Azimuth operator to configure authentication and authorization for Azimuth -itself using either OpenStack credentials directly or using a Keycloak realm to manage users. +An Azimuth operator can configure authentication and authorization for Azimuth itself using +either OpenStack credentials directly or using a realm in the Azimuth-managed Keycloak. Each +mechanism has pros and cons. An "Azimuth tenancy" is essentially a `Namespace` in the Azimuth Kubernetes cluster that holds the platform definitions and related resources for that tenancy (implemented as Kubernetes custom @@ -70,15 +71,21 @@ This section documents how this is acheived for each authentication method. ### Using OpenStack credentials Azimuth allows authenticating directly using credentials for the underlying OpenStack cloud, -with support for domain/username/password, application credentials and federated identity -providers configured in Keystone. +with support for domain/username/password, application credentials and Keystone federated +identity providers. In each case, Azimuth obtains a token that can be used to interact with the OpenStack APIs on behalf of the user. This token is _unscoped_, i.e. not associated with a specific OpenStack -project, but can be used to query the OpenStack projects that the user has access to (and hence -the Azimuth tenancies). Once the user enters a tenancy context in Azimuth, the unscoped token -can be exchanged for a _project-scoped_ token that allows Azimuth to manage resources in the -OpenStack project. +project, but can be used to query the OpenStack projects that the user has access to - these +projects correspond to the Azimuth tenancies that the user can access. Once the user enters +a tenancy context in Azimuth, the unscoped token can be exchanged for a _project-scoped_ token +that allows Azimuth to manage resources in the OpenStack project. + +When authenticating using OpenStack credentials, Azimuth will create the corresponding tenant +namespaces automatically when required. + +The following sequence diagram shows a typical flow for creating a platform in an Azimuth +tenancy using OpenStack authentication: ```mermaid sequenceDiagram @@ -87,31 +94,134 @@ sequenceDiagram participant N as Azimuth Tenant
Namespace participant O as OpenStack - U ->> A: List machines in tenancy X + U ->> A: Create platform in tenancy X opt Session cookie not present or unscoped token expired - A -->> U: Redirect to login page - U ->>+ A: Visit login page - A ->>- U: List of authentication methods + A ->> U: Authentication required + U ->> A: Visit login page + A ->> U: List of authentication methods alt Domain/username/password or application credential selected - U ->>+ A: Supply credentials - A ->>+ O: Request unscoped token using supplied credentials - O ->>- A: Return unscoped token for user - A -->>- U: Redirect to list machines
Set cookie containing unscoped token + U ->> A: Supply credentials + A ->> O: Request unscoped token using supplied credentials + O ->> A: Return unscoped token for user + A -->> U: Redirect to tenancy
Set cookie containing unscoped token else Keystone federated IDP selected - U ->>+ A: Keystone federated IDP selected - A -->>- U: Redirect user to Keystone federation URL - U ->>+ O: Visit Keystone federation URL + U ->> A: Keystone federated IDP selected + A -->> U: Redirect to Keystone federation URL + U ->> O: Visit Keystone federation URL O ->> O: Authenticate user with external IDP
May require additional redirects, e.g. for OIDC - O ->>- U: Return unscoped token to user's browser - U ->>+ A: Complete authentication by POSTing unscoped token - A -->>- U: Redirect to list machines
Set cookie containing unscoped token + O ->> U: Return unscoped token to user's browser + U ->> A: Complete authentication by POSTing unscoped token + A -->> U: Redirect to tenancy
Set cookie containing unscoped token + end + U ->> A: Re-submit create platform in tenancy X + end + A ->> O: Exchange unscoped token for scoped token for project X + O ->> A: Return scoped token for project X + opt Azimuth tenant namespace does not exist + A ->> N: Create tenant namespace + N ->> A: Namespace created successfully + end + A ->> O: Create application credential for platform + O ->> A: Return platform application credential data + A ->> N: Write application credential to secret + N ->> A: Secret written successfully + A ->> N: Create custom resources for platform + N ->> A: Resources created successfully + A ->> U: Platform created in tenancy X +``` + +### Using a Keycloak realm + +!!! warning "Technology preview" + + This authentication method is currently in technology preview and not recommended for + production. + + Fully automated configuration of the Keycloak realm is not yet supported in `azimuth-ops`, + so it is recommended that you enable backups for your Azimuth installation in order to + preserve the Keycloak database in the case of an unrecoverable failure. + +Azimuth also supports authenticating against a special realm in the Keycloak instance that is +deployed as part of an Azimuth installation. When using this authentication method, it is no +longer required that platform admins have accounts on the underlying OpenStack cloud - the +Azimuth operator can configure the Keycloak realm with any identity providers (e.g. Microsoft +Entra, Google, LDAP, OIDC) and policies (e.g. MFA) that are supported by Keycloak that they +need for users signing in to Azimuth. + +In this authentication method, an Azimuth tenant namespace must be _pre-created_ for each +OpenStack project that you want to use with Azimuth and a group must exist in the Keycloak +realm that is used to grant access to this tenancy - `azimuth-ops` handles the creation of +these namespaces and groups for the projects listed in your Azimuth configuration. Keycloak +can be configured to automatically map users from federated identity providers into these +groups if desired, or users can be manually added to the groups as needed. + +Azimuth authenticates users against the Keycloak realm using OpenID Connect, and the `groups` +claim from the resulting token is used to determine which Azimuth tenancies the user is +permitted to access. + +#### Obtaining an OpenStack credential + +Because users no longer have OpenStack credentials, Azimuth must now own the credentials that +are used to provision resources in the underlying cloud on behalf of users. For each OpenStack +project that you want to use Azimuth with, an application credential must be _pre-created_ and +stored in a `Secret` in the corresponding Azimuth tenant namespace. `azimuth-ops` handles the +creation of these secrets, but not the creation of the application credentials themselves - +these must be created ahead of time and placed in your Azimuth configuration. + +!!! warning "Unrestricted application credentials" + + The application credentials must be **unrestricted**, meaning that they have the ability + to create additional application credentials. This is so that Azimuth can still create the + per-platform application credentials that are used to manage platform resources. + +!!! tip "Service account recommended" + + It is recommended that Azimuth has a service account in the underlying OpenStack that owns + the application credentials used by Azimuth. This service account will need to belong to all + the projects that you wish to use Azimuth with. + + This avoids all of the application credentials used by Azimuth being tied to an individual + OpenStack user who may have access to the cloud revoked, e.g. if they leave the organisation. + +The following sequence diagram shows a typical flow for creating a platform in an Azimuth +tenancy using the Keycloak realm for authentication: + +```mermaid +sequenceDiagram + actor U as User + participant A as Azimuth Portal + participant N as Azimuth Tenant
Namespace + participant K as Keycloak Realm + participant O as OpenStack + + U ->> A: Create platform in tenancy X + opt Session cookie not present or ID token invalid or expired + A ->> U: Authentication required + U ->> A: Visit login page + A -->> U: Redirect to OIDC authorize URL + U ->> K: Visit OIDC authorize URL + opt User does not have a current Keycloak session + K -->> U: Redirect to login page + U ->> K: Visit login page + K ->> K: Authenticate user
This may redirect to an external IDP end + K -->> U: Redirect to OIDC callback URL + U ->> A: Visit OIDC callback URL + A ->> K: Request OIDC ID token + K ->> A: Return OIDC ID token with groups claim + A -->> U: Redirect to tenancy
Set cookie containing ID token + U ->> A: Re-submit create platform in tenancy X end - A ->>+ O: Exchange unscoped token for scoped token for project X - O ->>- A: Return scoped token for project X - A ->>+ O: List servers in project X - O ->>- A: List of servers in project X - A ->> U: List of machines in tenancy X + A ->> A: Verify that user is authorised for tenancy X
using groups claim from OIDC token + A ->> N: Read project application credential secret + N ->> A: Return project application credential data + A ->> O: Create application credential for platform + O ->> A: Return platform application credential data + A ->> N: Write platform application credential to secret + N ->> A: Secret written successfully + A ->> N: Create custom resources for platform + N ->> A: Resources created successfully + A ->> U: Platform created in tenancy X ``` ## Accessing platform services @@ -142,7 +252,7 @@ The following diagram shows the sequence of actions for a user accessing a platf ```mermaid sequenceDiagram actor U as User - participant P as Proxy + participant P as Zenith Proxy participant R as Keycloak Realm participant A as Azimuth Portal participant S as Platform Service