Commit cc5706c0 authored by Marc Barussaud's avatar Marc Barussaud Committed by Pierre Smeyers
Browse files

feat(AKS): add Azure Kubernetes Services support (as a variant)

parent 0d205ceb
Loading
Loading
Loading
Loading
+57 −4
Original line number Diff line number Diff line
@@ -653,12 +653,11 @@ include:

### Amazon Web service variant

This variant use the OIDC and [AWS STS](https://docs.aws.amazon.com/fr_fr/STS/latest/APIReference/welcome.html) in AWS to get credential
This variant use the OIDC and [AWS STS](https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html) in AWS to get credential

#### Prerequesite

- [Create an OpenID Connect (OIDC) identity provider in IAM
  ](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html)
- [Create an OpenID Connect (OIDC) identity provider in IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html)
- [Configure a web identity role](https://docs.gitlab.com/ci/cloud_services/aws/#configure-a-role-and-trust)
- Use a `K8S_KUBECTL_IMAGE` that contains also `aws-iam-authenticator` like `docker.io/alpine/k8s`

@@ -693,3 +692,57 @@ include:
      # specific OIDC config for prod
      aws-prod-oidc-role-arn: "arn:aws:iam::<project_id>:role/<role_name>"
```
### AKS variant

This variant allows to **deploy your applications** to [Azure Kubernetes Services](https://learn.microsoft.com/en-gb/azure/aks/what-is-aks) with OIDC and [kubelogin](https://azure.github.io/kubelogin/).

List of requirements before using this variant for deploying your charts:

1. You must have an AKS cluster,
2. You must have a managed identity or an application with enough permissions to make the required modifications,
3. You must have federated identity credentials for this managed identity or application.

#### Configuration

| Input / Variable                                          | Description                                                                                                               | Default value                                                           |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| `TBC_AZURE_PROVIDER_IMAGE`                                | The [Azure Auth Provider](https://gitlab.com/to-be-continuous/tools/azure-auth-provider) image to use (can be overridden) | `registry.gitlab.com/to-be-continuous/tools/azure-auth-provider:latest` |
| `azure-oidc-aud` / `AZURE_OIDC_AUD`                       | The `aud` claim for the JWT token used for [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/)        | `api://AzureADTokenExchange`                                            |
| `azure-client-id` / `AZURE_CLIENT_ID`                     | Client Id of the identity used by the [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/)             | _none_                                                                  |
| `azure-tenant-id` / `AZURE_TENANT_ID`                     | Azure Tenant Id of the target AKS                                                                                         | _none_                                                                  |
| `azure-review-client-id` / `AZURE_REVIEW_CLIENT_ID`       | Client Id of the identity used by the OIDC authentication for `review` env _(only define to override default)_            | _none_                                                                  |
| `azure-review-tenant-id` / `AZURE_REVIEW_TENANT_ID`       | Azure Tenant Id of the target AKS for `review` env _(only define to override default)_                                    | _none_                                                                  |
| `azure-integ-client-id` / `AZURE_INTEG_CLIENT_ID`         | Client Id of the identity used by the OIDC authentication for `integ` env _(only define to override default)_             | _none_                                                                  |
| `azure-integ-tenant-id` / `AZURE_INTEG_TENANT_ID`         | Azure Tenant Id of the target AKS for `integ` env _(only define to override default)_                                     | _none_                                                                  |
| `azure-staging-client-id` / `AZURE_STAGING_CLIENT_ID`     | Client Id of the identity used by the OIDC authentication for `staging` env _(only define to override default)_           | _none_                                                                  |
| `azure-staging-tenant-id` / `AZURE_STAGING_TENANT_ID`     | Azure Tenant Id of the target AKS for `staging` env _(only define to override default)_                                   | _none_                                                                  |
| `azure-prod-client-id` / `AZURE_PROD_CLIENT_ID`           | Client Id of the identity used by the OIDC authentication for `prod` env _(only define to override default)_              | _none_                                                                  |
| `azure-prod-tenant-id` / `AZURE_PROD_TENANT_ID`           | Azure Tenant Id of the target AKS for `prod` env _(only define to override default)_                                      | _none_                                                                  |

#### Example - Deploy to AKS

```yaml
include:
  # main template
  - component: $CI_SERVER_FQDN/to-be-continuous/helm/gitlab-ci-k8s@9.2.0
  # AKS auth variant
  - component: $CI_SERVER_FQDN/to-be-continuous/helm/gitlab-ci-k8s-aks@9.2.0
    inputs:
      # Example with one account for every environment
      azure-client-id: "12345678-acbd-abcd-acbd-1234567890ab"
      azure-tenant-id: "abcdef01-2345-6789-0123-abcdef012345"

variables:
  # Configure kubeconfig URLs per environment, here each cluster has the same name but is in a different resource groupe
  K8S_REVIEW_KUBECONFIG: "@url@http://azure-auth-provider/kubeconfig?subscription_id=01020304-abcd-effe-dcba-506070809000&resource_group_name=review_cluster&resource_name=my-app"
  K8S_STAGING_KUBECONFIG: "@url@http://azure-auth-provider/kubeconfig?subscription_id=01020304-abcd-effe-dcba-506070809000&resource_group_name=staging_cluster&resource_name=my-app"
  K8S_PROD_KUBECONFIG: "@url@http://azure-auth-provider/kubeconfig?subscription_id=01020304-abcd-effe-dcba-506070809000&resource_group_name=prod_cluster&resource_name=my-app"
```

#### How it works

The AKS variant template provides:

**AKS kubeconfig via Azure Auth Provider**: Users configure the `K8S_<ENV>_KUBE_CONFIG` variable with a URL pattern (`@url@http://azure-auth-provider/kubeconfig?subscription_id=...`) that dynamically retrieves a kubeconfig that will be used by the kubelogin exec plugin.

The authentication uses [GitLab's OIDC integration with AWS](https://docs.gitlab.com/ci/cloud_services/azure/), which means you don't need to manage long-lived AAD credentials in your CI/CD variables.
+62 −0
Original line number Diff line number Diff line
@@ -420,6 +420,68 @@
          "advanced": true
        }
      ]
    },
    {
      "id": "azure-auth-provider",
      "name": "Azure Kubernetes Service",
      "description": "This variant uses OpenID connect and kubelogin to retrieve temporary credentials.",
      "template_path": "templates/gitlab-ci-k8s-aks.yml",
      "variables": [
        {
          "name": "AZURE_OIDC_AUD",
          "description": "The `aud` claim for the JWT token used for [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/)",
          "default": "api://AzureADTokenExchange",
          "advanced": true
        },
        {
          "name": "AZURE_CLIENT_ID",
          "description": "Client Id of the identity used by the [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/)"
        },
        {
          "name": "AZURE_REVIEW_CLIENT_ID",
        "description": "Client Id of the identity used by the [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/) for `review` env _(only define to override default)_",
          "advanced": true
        },
        {
          "name": "AZURE_INTEG_CLIENT_ID",
          "description": "Client Id of the identity used by the [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/) for `integ` env _(only define to override default)_",
          "advanced": true
        },
        {
          "name": "AZURE_STAGING_CLIENT_ID",
          "description": "Client Id of the identity used by the [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/) for `staging` env _(only define to override default)_",
          "advanced": true
        },
        {
          "name": "AZURE_PROD_CLIENT_ID",
          "description": "Client Id of the identity used by the [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/) for `prod` env _(only define to override default)_",
          "advanced": true
        },
        {
          "name": "AZURE_TENANT_ID",
          "description": "Azure Tenant Id of the target AKS"
        },
        {
          "name": "AZURE_REVIEW_TENANT_ID",
          "description": "Azure Tenant Id of the target AKS for `review` env _(only define to override default)_",
          "advanced": true
        },
        {
          "name": "AZURE_INTEG_TENANT_ID",
          "description": "Azure Tenant Id of the target AKS for `integ` env _(only define to override default)_",
          "advanced": true
        },
        {
          "name": "AZURE_STAGING_TENANT_ID",
          "description": "Azure Tenant Id of the target AKS for `staging` env _(only define to override default)_",
          "advanced": true
        },
        {
          "name": "AZURE_PROD_TENANT_ID",
          "description": "Azure Tenant Id of the target AKS for `prod` env _(only define to override default)_",
          "advanced": true
        }
      ]
    }
  ]
}
+104 −0
Original line number Diff line number Diff line

# =====================================================================================================================
# === AKS Auth template variant
# =====================================================================================================================
spec:
  inputs:
    azure-oidc-aud:
      description: The `aud` claim for the JWT token used for [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/)
      default: 'api://AzureADTokenExchange'
    azure-client-id:
      description: Client Id of the identity used by the [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/)
      default: ''
    azure-tenant-id:
      description: Azure Tenant Id of the target AKS
      default: ''
    azure-review-client-id:
      description: Client Id of the identity used by the [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/) for `review` env _(only define to override default)_
      default: ''
    azure-review-tenant-id:
      description: Azure Tenant Id of the target AKS for `review` env _(only define to override default)_
      default: ''
    azure-integ-client-id:
      description: Client Id of the identity used by the [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/) for `integ` env _(only define to override default)_
      default: ''
    azure-integ-tenant-id:
      description: Azure Tenant Id of the target AKS for `integ` env _(only define to override default)_
      default: ''
    azure-staging-client-id:
      description: Client Id of the identity used by the [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/) for `staging` env _(only define to override default)_
      default: ''
    azure-staging-tenant-id:
      description: Azure Tenant Id of the target AKS for `staging` env _(only define to override default)_
      default: ''
    azure-prod-client-id:
      description: Client Id of the identity used by the [OIDC authentication](https://docs.gitlab.com/ci/cloud_services/azure/) for `prod` env _(only define to override default)_
      default: ''
    azure-prod-tenant-id:
      description: Azure Tenant Id of the target AKS for `prod` env _(only define to override default)_
      default: ''


---
variables:
  TBC_AZURE_PROVIDER_IMAGE: registry.gitlab.com/to-be-continuous/tools/azure-auth-provider:latest
  AZURE_OIDC_AUD: $[[ inputs.azure-oidc-aud ]]
  AZURE_CLIENT_ID: $[[ inputs.azure-client-id ]]
  AZURE_TENANT_ID: $[[ inputs.azure-tenant-id ]]
  AZURE_REVIEW_CLIENT_ID: $[[ inputs.azure-review-client-id ]]
  AZURE_REVIEW_TENANT_ID: $[[ inputs.azure-review-tenant-id ]]
  AZURE_INTEG_CLIENT_ID: $[[ inputs.azure-integ-client-id ]]
  AZURE_INTEG_TENANT_ID: $[[ inputs.azure-integ-tenant-id ]]
  AZURE_STAGING_CLIENT_ID: $[[ inputs.azure-staging-client-id ]]
  AZURE_STAGING_TENANT_ID: $[[ inputs.azure-staging-tenant-id ]]
  AZURE_PROD_CLIENT_ID: $[[ inputs.azure-prod-client-id ]]
  AZURE_PROD_TENANT_ID: $[[ inputs.azure-prod-tenant-id ]]

.k8s-azure-azki:
  - |
    if [[ "$AZURE_JWT" ]]
    then
      if command -v kubelogin > /dev/null
      then
        echo '[INFO] kubelogin already installed'
      else
        echo '[INFO] Installing kubelogin'
        decoded=$(mktemp)
        errors=$(mktemp)
        if wget -T "${TBC_SECRET_URL_TIMEOUT:-5}" -O /tmp/kubelogin.zip https://github.com/Azure/kubelogin/releases/download/v0.2.17/kubelogin-linux-amd64.zip 2> "${errors}"
        then
          unzip /tmp/kubelogin.zip -d /tmp
          rm /tmp/kubelogin.zip
          mv /tmp/bin/linux_amd64/kubelogin /usr/local/bin/kubelogin
        else
          echo '[ERROR] Failed to download kubelogin'
          cat "${errors}"
        fi
      fi
      echo "Configuring kubelogin for Workload Identity"
      k8s_config=${ENV_KUBE_CONFIG:-${K8S_DEFAULT_KUBE_CONFIG}}
      echo -ne "${k8s_config}" > "$CI_PROJECT_DIR/.azure_kubeconfig"
      export ENV_KUBE_CONFIG="$CI_PROJECT_DIR/.azure_kubeconfig"
      echo "${AZURE_JWT}" > "$CI_BUILDS_DIR/.auth_token.jwt"
      kubelogin convert-kubeconfig --login workloadidentity --kubeconfig "$CI_PROJECT_DIR/.azure_kubeconfig" --federated-token-file "$CI_BUILDS_DIR/.auth_token.jwt"
    else
      echo '[WARN] $AZURE_JWT is not set: cannot setup Azure Kubelogin Workload Identity authentication'
    fi

.k8s-env-base:
  services:
    - name: "$TBC_TRACKING_IMAGE"
      command: ["--service", "kubernetes", "9.2.0"]
    - name: "$TBC_AZURE_PROVIDER_IMAGE"
      alias: "azure-auth-provider"
  before_script:
    - !reference [.k8s-scripts]
    - !reference [.k8s-azure-azki]
    - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
    - k8s_login
  variables:
    #  have to be explicitly declared in the YAML to be exported to the service
    AZURE_JWT: $AZURE_JWT
  id_tokens:
    AZURE_JWT:
      aud: "$AZURE_OIDC_AUD"