Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add doc for workload identity #3770

Merged
merged 1 commit into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
- [Windows](./topics/windows.md)
- [Flatcar](./topics/flatcar.md)
- [WebAssembly / WASI Pods](./topics/wasi.md)
- [Workload Identity](./topics/workload-identity.md)
- [Development](./developers/development.md)
- [Kubernetes Developers](./developers/kubernetes-developers.md)
- [Releasing](./developers/releasing.md)
Expand Down
32 changes: 26 additions & 6 deletions docs/book/src/topics/multitenancy.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,31 @@

To enable single controller multi-tenancy, a different Identity can be added to the Azure Cluster that will be used as the Azure Identity when creating Azure resources related to that cluster.

This is achieved using the [aad-pod-identity](https://azure.github.io/aad-pod-identity) library.
This is achieved using [workload identity](https://azure.github.io/azure-workload-identity). Workload identity is the next iteration of the now deprecated [aad-pod-identity](https://azure.github.io/aad-pod-identity).

## Identity Types

### Service Principal With Client Password
### Workload Identity (Recommended)

Follow this [link](./workload-identity.md) for a quick start guide on setting up workload identity.

Once you've set up the management cluster with the workload identity (see link above), the corresponding values should be used to create an `AzureClusterIdentity` resource. Create an `azure-cluster-identity.yaml` file with the following content:

```yaml
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: AzureClusterIdentity
metadata:
name: cluster-identity
spec:
type: WorkloadIdentity
tenantID: <your-tenant-id>
clientID: <your-client-id>
allowedNamespaces:
list:
- <cluster-namespace>
```

### AAD Pod Identity using Service Principal With Client Password (Deprecated)

Once a new SP Identity is created in Azure, the corresponding values should be used to create an `AzureClusterIdentity` Kubernetes resource. Create an `azure-cluster-identity.yaml` file with the following contents:

Expand Down Expand Up @@ -49,7 +69,7 @@ data:
clientSecret: <client-secret-of-SP-identity>
```

### Service Principal With Certificate
### AAD Pod Identity using Service Principal With Certificate (Deprecated)

Once a new SP Identity is created in Azure, the corresponding values should be used to create an `AzureClusterIdentity` resource:

Expand Down Expand Up @@ -94,7 +114,7 @@ data:
password: PASSWORD
```

### User-Assigned Managed Identity
### AAD Pod Identity using User-Assigned Managed Identity (Deprecated)

<aside class="note">

Expand Down Expand Up @@ -125,7 +145,7 @@ spec:
tenantID: <azure-tenant-id>
clientID: <client-id-of-user-assigned-identity>
resourceID: <resource-id-of-user-assigned-identity>
allowedNamespaces:
allowedNamespaces:
list:
- <cluster-namespace>
```
Expand Down Expand Up @@ -189,4 +209,4 @@ spec:
namespace: <namespace-of-identity>
```

For more details on how aad-pod-identity works, please check the guide [here](https://azure.github.io/aad-pod-identity/docs/).

206 changes: 206 additions & 0 deletions docs/book/src/topics/workload-identity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
# Workload Identity

Azure AD Workload identity is the next iteration of Azure AD Pod identity
that enables Kubernetes applications (e.g. CAPZ) to access Azure cloud
resources securely with Azure Active Directory.

This document describes a quick start guide of using workload identity and
assumes that you have access to Azure cloud.

Workload identity is currently worked upon and cloud provider azure
integration is in progress. Please refer to [this](https://github.com/kubernetes-sigs/cluster-api-provider-azure/issues/3589) issue for details.
For more information, please refer to the [proposal](https://github.com/kubernetes-sigs/cluster-api-provider-azure/blob/main/docs/proposals/20221611-workload-identity-integration.md)

## Workload Identity Quick Start Guide

### Setting Up Management Cluster on Kind

- Create a public and private key pair. For example, you can generate the
key pairs using OpenSSL.

Generate a private key called `sa.key` using the following command:
```bash
$ openssl genrsa -out sa.key 2048
```

Set the environment variable `SERVICE_ACCOUNT_SIGNING_KEY_FILE` to the path of the
generated `sa.key`. This ENV var will be used in the upcoming step.
Note: You can use `readlink -f sa.key` to get the absolute path of the key file.

Generate a public key using the private key.
```bash
$ openssl rsa -in sa.key -pubout -out sa.pub
```
Set the environment variable `SERVICE_ACCOUNT_KEY_FILE` to the path of the
generated `sa.pub`. This ENV var will be used in the upcoming step.

- Create and upload Discovery and JWKS document using this [link](https://azure.github.io/azure-workload-identity/docs/installation/self-managed-clusters/oidc-issuer.html)

- At this stage, you will need to create a federated identity credential.
- You can create that either with Azure AD application or user-assigned
identity. Please note that user assigned identity will need to be created
regardless because cloud provider azure integration is not yet done. The
steps are mentioned in the next section of workload cluster creation.
- The next list items links to steps on creating the federated
identity credential. You will need to set up several environment
variables:
- `SERVICE_ACCOUNT_NAMESPACE` : Namespace where the capz-manager pod
will run.
- `SERVICE_ACCOUNT_NAME` : Name of the capz-manager k8s service account.
sonasingh46 marked this conversation as resolved.
Show resolved Hide resolved
- `SERVICE_ACCOUNT_ISSUER` : This is the path of the Azure storage
container which you created in the previous step which is:
`"https://${AZURE_STORAGE_ACCOUNT}.blob.core.windows.net/${AZURE_STORAGE_CONTAINER}/"`

- Create a federated identity credential using the steps outlined [here](https://azure.github.io/azure-workload-identity/docs/topics/federated-identity-credential.html)
You can either use `user-assigned-identity` or `AD application` to create federated identity credential and add `contributor` role to it.

- Create a Kind cluster with necessary flags with the following command:

```bash
cat <<EOF | kind create cluster --name azure-workload-identity --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraMounts:
- hostPath: ${SERVICE_ACCOUNT_KEY_FILE}
containerPath: /etc/kubernetes/pki/sa.pub
- hostPath: ${SERVICE_ACCOUNT_SIGNING_KEY_FILE}
containerPath: /etc/kubernetes/pki/sa.key
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
apiServer:
extraArgs:
service-account-issuer: ${SERVICE_ACCOUNT_ISSUER}
service-account-key-file: /etc/kubernetes/pki/sa.pub
service-account-signing-key-file: /etc/kubernetes/pki/sa.key
controllerManager:
extraArgs:
service-account-private-key-file: /etc/kubernetes/pki/sa.key
EOF
```

- Initialize a management cluster using `clusterctl` using the below command.
If you do not have `clusterctl` installed, then follow this [link](https://cluster-api.sigs.k8s.io/user/quick-start.html#install-clusterctl)
to install.
```bash
$ clusterctl init --infrastructure azure
```

### Creating a Workload Cluster

- Create a user-assigned identity using the below steps:
- [Create](https://learn.microsoft.com/en-gb/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities?pivots=identity-mi-methods-azp#create-a-user-assigned-managed-identity)
a user-assigned managed identity in Azure. Save its name which will be used later.
- [Create a role assignment](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal-managed-identity)
to give the identity Contributor access to the Azure subscription where the workload cluster will be created.

- Before generating a workload cluster YAML configuration set the
following environment variables.
sonasingh46 marked this conversation as resolved.
Show resolved Hide resolved
```bash
export AZURE_SUBSCRIPTION_ID=<your-azure-subscription-id>
# This is the client ID of the AAD app or user-assigned identity that you used to created the federated identity.
export AZURE_CLIENT_ID=<your-azure-client-id>
sonasingh46 marked this conversation as resolved.
Show resolved Hide resolved
export AZURE_TENANT_ID=<your-azure-tenant-id>
export AZURE_CONTROL_PLANE_MACHINE_TYPE="Standard_B2s"
mboersma marked this conversation as resolved.
Show resolved Hide resolved
export AZURE_NODE_MACHINE_TYPE="Standard_B2s"
export AZURE_LOCATION="eastus"
sonasingh46 marked this conversation as resolved.
Show resolved Hide resolved

# Identity secret. Though these are not used in workload identity, we still
# need to set them for the sake of generating the workload cluster YAML configuration
export AZURE_CLUSTER_IDENTITY_SECRET_NAME="cluster-identity-secret"
export CLUSTER_IDENTITY_NAME="cluster-identity"
export AZURE_CLUSTER_IDENTITY_SECRET_NAMESPACE="default"
```
- Generate a workload cluster template using the following command.

```bash
clusterctl generate cluster azwi-quickstart --kubernetes-version v1.27.3 --worker-machine-count=3 > azwi-quickstart.yaml
```

- Edit the generated `azwi-quickstart.yaml` to make the following changes for
workload identity to the `AzureClusterIdentity` object.
- Change the type to `WorkloadIdentity`.
sonasingh46 marked this conversation as resolved.
Show resolved Hide resolved
- Remove the `clientSecret` spec.

The AzureClusterIdentity specification should look like the following.
```yaml
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: AzureClusterIdentity
metadata:
name: cluster-identity
CecileRobertMichon marked this conversation as resolved.
Show resolved Hide resolved
spec:
type: WorkloadIdentity
allowedNamespaces:
list:
- <cluster-namespace>
tenantID: <your-tenant-id>
clientID: <your-client-id>
```

- Change the `AzureMachineTemplate` for both control plane and worker to include user-assigned-identity by
adding the following in its `spec`.
```yaml
identity: UserAssigned
userAssignedIdentities:
- providerID: /subscriptions/${AZURE_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/${USER_ASSIGNED_IDENTITY_NAME}
sonasingh46 marked this conversation as resolved.
Show resolved Hide resolved
```
A sample `AzureMahineTemplate` after the edit should look like the below:

```yaml
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: AzureMachineTemplate
metadata:
name: ${CLUSTER_NAME}-md-0
namespace: default
spec:
template:
spec:
osDisk:
diskSizeGB: 128
osType: Linux
sshPublicKey: ${AZURE_SSH_PUBLIC_KEY_B64:=""}
identity: UserAssigned
userAssignedIdentities:
- providerID: /subscriptions/${AZURE_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/${USER_ASSIGNED_IDENTITY_NAME}
vmSize: ${AZURE_NODE_MACHINE_TYPE}
```

- At this stage, you can apply this yaml to create a workload cluster.

Notes:
- Please follow this [link](https://github.com/kubernetes-sigs/cluster-api-provider-azure/blob/main/templates/test/ci/cluster-template-prow-workload-identity.yaml)
to see a workload cluster yaml configuration that uses workload identity.
- Creating a workload cluster via workload identity will be
simplified after [this](https://github.com/kubernetes-sigs/cluster-api-provider-azure/issues/3589) issue is resolved.

## Debugging

### No matching federated identity record found

If you see logs like below, double check if the service account URL is exactly same on apiserver as
that in the federated credential.
```bash
"error": "invalid_request",
"error_description": "AADSTS70021: No matching federated identity record found for presented assertion. Assertion
```

### Authorization failed when using user-assigned identity

If you see error message similar to the following in the `AzureCluster` object,
this can be because the user-assigned identity does not have required permission.

```bash
Message: group failed to create or update. err: failed to get existing resource
demo/demo(service: group): resources.GroupsClient#Get: Failure
responding to request: StatusCode=403 -- Original Error: autorest/azure:
Service returned an error. Status=403 Code="AuthorizationFailed"
Message="The client '<id-redacted>' with object id '<id-redacted>' does not have
authorization to perform action 'Microsoft.Resources/subscriptions/resourcegroups/read'
over scope '/subscriptions/<sub-id-redacted>/resourcegroups/ashu-test' or the
scope is invalid. If access was recently granted, please refresh your
credentials.". Object will be requeued after 15s
```

Add `contributor` role to the user-assigned identity and this should fix it.