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

Azure IAM docs & tutorials #206

Merged
merged 25 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e59ad19
Add azure IAM code samples
amitlicht Mar 7, 2024
23e43c2
Read account & container name from env
amitlicht Mar 7, 2024
462e537
rename storage account
amitlicht Mar 7, 2024
6d0fea0
Prettify output
amitlicht Mar 7, 2024
08575df
Merge remote-tracking branch 'origin/main' into amitlicht/azure_iam_t…
amitlicht Mar 10, 2024
0d10327
Azure IAM tutorial - WIP
amitlicht Mar 10, 2024
a8c377f
Update reference
amitlicht Mar 10, 2024
6a2e9c9
Fixes
amitlicht Mar 10, 2024
4cd99ee
Add icons
amitlicht Mar 10, 2024
1cd9f27
Remove patch deployment
amitlicht Mar 10, 2024
5fcc229
Remove subscription ID & resource group from clientintents (auto-dete…
amitlicht Mar 10, 2024
3b6114d
Touchups
amitlicht Mar 10, 2024
450750f
Added new lines
tomergreenwald Mar 10, 2024
b40c1b5
let az cli figure out storage account SKU on its own
amitlicht Mar 10, 2024
856696e
Fix linebreak
amitlicht Mar 10, 2024
e2a76c0
Improving client app
amitlicht Mar 10, 2024
5249586
Improving client app
amitlicht Mar 10, 2024
ebf6619
More touchups
amitlicht Mar 10, 2024
0a2eed2
Document the label
amitlicht Mar 10, 2024
c60dd19
Update docs/features/azure-iam/tutorials/azure-iam-aks.mdx
amitlicht Mar 11, 2024
d541f94
Update docs/features/azure-iam/tutorials/azure-iam-aks.mdx
amitlicht Mar 11, 2024
4d59d80
Remove subscription & resource group from intents format
amitlicht Mar 11, 2024
0c08fc6
Fix the tutorial to work with custom storage accounts without modifyi…
amitlicht Mar 12, 2024
0c6485f
Merge branch 'amitlicht/azure_iam_tutorial' of github.com:otterize/do…
amitlicht Mar 12, 2024
64e19ff
Add an early-access note to Azure IAM
amitlicht Mar 14, 2024
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
8 changes: 8 additions & 0 deletions docs/features/azure-iam/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "Azure IAM",
"position": 2,
"collapsed": true,
"customProps": {
"image": "/img/icons/azure.png"
}
}
63 changes: 63 additions & 0 deletions docs/features/azure-iam/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
sidebar_position: 1
title: Azure IAM | Overview
hide_table_of_contents: true
hide_title: true
---

import DocsLinkCard from "@site/src/components/LinkCard";

export const tutorials = [
{
title: 'Automate Azure IAM for AKS',
description: 'Create just-in-time Azure workload identities & role assignments that are kept in sync with your workloads',
url: '/features/azure-iam/tutorials/azure-iam-aks'
},
];


# Azure IAM

Otterize can create just-in-time Azure IAM workload identities & role assignments for your workloads running on AKS Kubernetes clusters, greatly simplifying the lifecycle of managing Azure IAM identities and roles.

### Tutorials

To learn how to use the Intents Operator and Credentials Operator to manage just-in-time Azure IAM access, check out the tutorial.
<DocsLinkCard items={tutorials} colSize={"sm"}/>


### How does Otterize work with Azure IAM?

1. First, the AKS cluster must have [Otterize installed](/overview/installation), as well as the Otterize Azure integration configured.
2. To have a workload identity created for a pod, label the pod with `credentials-operator.otterize.com/create-azure-workload-identity: "true"`
3. The credentials operator will create an Azure workload identity and federated identity credential bound to the pod's ServiceAccount. The ServiceAccount will be annotated automatically.
4. At this point, the pod is able to assume the identity, but it does not have the permissions to perform any actions.
We will need to create a ClientIntents YAML for the access the service requires and apply it to our cluster.
Below is an example of a ClientIntents file for accessing an Azure Storage Blobs bucket.
View the [reference](/features/azure-iam/reference) to learn more about the Azure IAM ClientIntents syntax.
5. Once the intent is applied, the intents operator will create a new role assignment, which will be attached to the workload identity with the appropriate access.
6. Done!

```yaml
apiVersion: k8s.otterize.com/v1alpha3
kind: ClientIntents
metadata:
name: client
namespace: otterize-tutorial-azure-iam
spec:
service:
name: client
calls:
# replace 00000000-0000-0000-0000-000000000000 with your Azure subscription ID
- name: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/otterizetutorialazureiam/blobServices/default/containers/test"
type: azure
azureRoles:
- "Storage Blob Data Contributor"
```

### Automatically generating ClientIntents for Azure IAM

Figuring out which access you need for Azure can be a painful, trial and error process, and something you _must_ do if you're tightening production access.

Otterize is getting ready to release support for using existing traffic to generate least-privilege Azure IAM policies. Keen to try this out as part of early access? Sign up to the [Early Access Beta Program](https://otterize.com/EarlyAccessBetaProgram) and we'll be in touch!

44 changes: 44 additions & 0 deletions docs/features/azure-iam/reference.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
sidebar_position: 3
title: Reference
---

### ClientIntents example (YAML)

```yaml
apiVersion: k8s.otterize.com/v1alpha3
kind: ClientIntents
metadata:
# The name of the pod that will be granted access
name: client
spec:
service:
name: client
calls:
# The Azure resource ID that references the resource(s) for the authorization
# replace 00000000-0000-0000-0000-000000000000 with your Azure subscription ID
- name: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/otterizeazureiamtutorial/blobServices/default/containers/otterizeazureiamtutorialcontainer"
type: azure
# one or more Azure roles that will be provided to the specified resources
azureRoles:
- "Storage Blob Data Contributor"
```

### Annotations

| Key | Description | Default |
|------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|
| `credentials-operator.otterize.com/create-azure-workload-identity` | By setting to **true** the credential operator will create an Azure workload identity the associated pod | `false` |


### Helm Chart options

| Key | Description | Default |
|------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|
| `global.azure.enabled` | Enable or disable Azure integration | `false` |
| `azure.userAssignedIdentityID` | ID of the user assigned identity used by the operator to access Azure. | `(none)` |
| `azure.subscriptionID` | ID of the Azure subscription in which the AKS cluster is deployed. | `(none)` |
| `azure.resoureceGroup` | Name of the Azure resource group in which the AKS cluster is deployed. | `(none)` |
| `azure.aksClusterName` | Name of the AKS cluster in which the operator is deployed. | `(none)` |

View the [Helm chart reference](/reference/configuration/otterize-chart) for all other options
5 changes: 5 additions & 0 deletions docs/features/azure-iam/tutorials/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"label": "Tutorials",
"position": 2,
"collapsed": false
}
270 changes: 270 additions & 0 deletions docs/features/azure-iam/tutorials/azure-iam-aks.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
---
sidebar_position: 2
title: Automate Azure IAM for AKS
image: /img/quick-tutorials/azure-iam-aks/social.png
---


Otterize automates Azure IAM identities and role assignments for your Azure AKS workloads, all in Kubernetes.

In this tutorial, we will:

- Optionally, spin up an AKS cluster, install the Otterize Kubernetes operator on it, and configure it to manage Azure IAM.
- Deploy a client pod that lists files in an Azure Blog Storage container.
- Label the client pod, telling the credentials operator to link its Kubernetes ServiceAccount with an Azure workload identity created for it.
- Create a `ClientIntents` resource allowing the client pod to access Azure Blob Storage, that tells the intents operator to create a role assignment and associate it with the previously created workload identity.
- See that the client is now able to list files in the Azure Blob Storage container.

## Prerequisites
Already have Otterize deployed with the Azure IAM integration configured on your cluster? [Skip to the tutorial.](#tutorial)


### 1. Install the Azure CLI
Follow the installation instructions for the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli).

### 2. Create an Azure AKS cluster
Before you start, you'll need an Azure AKS cluster, with OIDC issuer & workload identity enabled.

<details>
<summary>How to set up an Azure AKS cluster using the Azure CLI</summary>


Export the following environment variables:
```bash
export LOCATION="eastus"
export RESOURCE_GROUP="otterizeAzureIAMTutorialResourceGroup"
export AKS_CLUSTER_NAME="otterizeAzureIAMTutorialAKSCluster"
```

Create a resource group:
```bash
az group create --name $RESOURCE_GROUP --location $LOCATION
```

Create an AKS cluster, with OIDC issuer and workload identity enabled:
```bash
az aks create -g $RESOURCE_GROUP -n $AKS_CLUSTER_NAME --node-count 1 --enable-oidc-issuer --enable-workload-identity --generate-ssh-keys
```

</details>

Alternatively, update an existing AKS cluster to enable OIDC issuer and workload identity:

<details>
<summary>How to update an existing AKS cluster using the Azure CLI</summary>

Export the following environment variables:
```bash
export LOCATION="<YOUR_LOCATION>"
export RESOURCE_GROUP="<YOUR_RESOURCE_GROUP>"
export AKS_CLUSTER_NAME="<YOUR_AKS_CLUSTER_NAME>"
```

Update the AKS cluster to enable OIDC issuer and workload identity:
```bash
az aks update -g $RESOURCE_GROUP -n $AKS_CLUSTER_NAME --enable-oidc-issuer --enable-workload-identity
```

</details>



Don't forget to configure your kubeconfig for your cluster. If using the example cluster above, use this command:
```bash
az aks get-credentials -n $AKS_CLUSTER_NAME -g $RESOURCE_GROUP
```

### 2. Deploy Otterize for Azure IAM
To deploy Otterize, head over to [Otterize Cloud](https://app.otterize.com) and:

1. Create a Kubernetes cluster on the [Integrations page](https://app.otterize.com/integrations), and follow the instructions. *Make sure to enable enforcement mode for this tutorial.* If you already have a Kubernetes cluster connected, skip this step.
amitlicht marked this conversation as resolved.
Show resolved Hide resolved

2. Create an Azure IAM integration on the [Integrations page](https://app.otterize.com/integrations).
- Input your Azure tenant & subscription IDs. These are available in the Azure portal, or by running the following command:
```bash
az account list --output table
```
- If you are using the cluster from the previous step, the resource group name is `otterizeAzureIAMTutorialResourceGroup` and the cluster name is `otterizeAzureIAMTutorialAKSCluster`.

Once the Azure integration is configured, you'll be presented with instructions for configuring your Otterize integration with Azure IAM support.
This creates a managed identity and federated identity credential for the Otterize Kubernetes operator, and assigns it the resource group owner role on the resource group containing your AKS cluster, so that it is able to manage identitiies and role assignments for your AKS workloads.
This setup is required once per-cluster.

After terraform has configured your cluster, click Next and you'll be presented with the configuration for deploying Otterize.
amitlicht marked this conversation as resolved.
Show resolved Hide resolved
Since you now have the Azure integration enabled, you need to redeploy Otterize with Azure integration enabled flag, providing it the client ID for the managed identity created during the terraform installation.

## Tutorial

### Create an Azure Blob Storage account & container
Create a general-purpose storage account using the Azure CLI:
```bash
export STORAGE_ACCOUNT_NAME=otterizeazureiamtutorial
az storage account create \
--name $STORAGE_ACCOUNT_NAME \
--resource-group $RESOURCE_GROUP \
--location $LOCATION
```

Create a container in the storage account:
```bash
export STORAGE_CONTAINER_NAME=otterizeazureiamtutorialcontainer
az storage container create \
--account-name $STORAGE_ACCOUNT_NAME \
--name $STORAGE_CONTAINER_NAME
```

Upload a blob to the storage container:
```bash
echo "Hello, Azure integration" > testfile.txt
az storage blob upload \
--account-name $STORAGE_ACCOUNT_NAME \
--container-name $STORAGE_CONTAINER_NAME \
--file testfile.txt \
--name testfile.txt
```

### Deploy the sample client

```bash
kubectl create namespace otterize-tutorial-azure-iam
kubectl apply -n otterize-tutorial-azure-iam -f ${ABSOLUTE_URL}/code-examples/azure-iam-aks/client.yaml
```

<details>
<summary>Expand to see the deployment YAML</summary>

```yaml
{@include: ../../../../static/code-examples/azure-iam-aks/client.yaml}
```

</details>


### View logs for the client - access denied
The client logs will show that the Azure client ID environment variable is not set.
This is because no Azure workload identity has been created for the client pod yet.

```text
Client - The time is: Sun Mar 10 18:40:37 UTC 2024

Azure client ID not set
```

### Label the client pod to create an Azure workload identity
Label the client pod so that the Otterize credentials operator creates an Azure workload identity for it and binds its Kubernetes ServiceAccount to the newly created identity.
```yaml
metadata:
labels:
credentials-operator.otterize.com/create-azure-workload-identity: "true"
```

To do this, we won't be labeling the pod directly, but instead patching the `template` attribute of the `Deployment` we created earlier so that it updates the pod.

```bash
kubectl patch deployment -n otterize-tutorial-azure-iam client -p '{"spec": {"template":{"metadata":{"labels":{"credentials-operator.otterize.com/create-azure-workload-identity":"true"}}}} }'
```

#### An Azure workload identity was created for the client pod
Let's inspect the created managed identity
```bash
az identity list --query "[?starts_with(name,'ottr-uai-')]" --output table
```

In the output, you should see that a managed identity was created for the client workload, with the name starting with `ottr-uai-otterize-tutorial-azure-iam-client-...`:
```bash
Name Location TenantId PrincipalId ClientId ResourceGroup
------------------------------------------------------------------------------------ ---------- ------------------------------------ ------------------------------------ ------------------------------------ ---------------------------------
ottr-uai-otterize-tutorial-azure-iam-client-otterizeAzureIAMTutorialAKSCluster-XXXXX eastus 00000000-0000-0000-0000-000000000000 00000000-0000-0000-0000-000000000000 00000000-0000-0000-0000-000000000000 otterizeAzureIAMTutorialResourceGroup
````

You could also inspect the federated identity credential created for the client workload:
```bash
export WORKLOAD_IDENTITY_NAME=$(az identity list --query "[?starts_with(name,'ottr-uai-otterize-tutorial-azure-iam-client-$AKS_CLUSTER_NAME')].name" -o tsv )
az identity federated-credential list --identity-name $WORKLOAD_IDENTITY_NAME --resource-group $RESOURCE_GROUP --output table --query "[].{name:name, subject:subject}"
```

In the output, you should see that a federated identity credential was created for the client workload:
```bash
Name Subject
------------------------------------------------------------------------------------ --------------------------------------------------------
ottr-fic-otterize-tutorial-azure-iam-client-otterizeAzureIAMTutorialAKSCluster-XXXXX system:serviceaccount:otterize-tutorial-azure-iam:client
```

#### The Kubernetes ServiceAccount was annotated with the workload identity ID
The credentials operator automatically annotated the Kubernetes ServiceAccount for the client pod with the newly created workload identity

Let's look at the service account:
```bash
kubectl get serviceaccount -n otterize-tutorial-azure-iam client -o yaml
```

```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
# highlight-next-line
azure.workload.identity/client-id: 6fda2902-d98c-40f6-800d-29d5856e359a
name: client
namespace: otterize-tutorial-azure-iam
```


### Apply intents to create the necessary IAM role assignments

By annotating the pod, we've created a workload identity.
We now need to specify what we need to access, and the intents operator will create an Azure IAM role assignment accordingly.

We will specify the following ClientIntents, granting the `Storage Blob Data Contributor` permission to the `otterizeazureiamtutorialcontainer` container in the `otterizeazureiamtutorial` storage account.
```yaml
{@include: ../../../../static/code-examples/azure-iam-aks/clientintents.yaml}
```

To apply these intents, run the following command:
```bash
kubectl apply -n otterize-tutorial-azure-iam -f ${ABSOLUTE_URL}/code-examples/azure-iam-aks/clientintents.yaml
```

### The client can now list files in the Azure Blob Storage container!

Let's look at the client logs again to see that no more errors are being reported:
```bash
kubectl logs -f -n otterize-tutorial-azure-iam deploy/client
```

```text
Client - The time is: Sun Mar 10 18:53:24 UTC 2024

Logging in using federated identity credentials
CloudName HomeTenantId IsDefault Name State TenantId
----------- ------------------------------------ ----------- -------------------- ------- ------------------------------------
AzureCloud 00000000-0000-0000-0000-000000000000 True Azure subscription 1 Enabled 00000000-0000-0000-0000-000000000000

Listing storage blob container otterizeazureiamtutorialcontainer in storage account otterizeazureiamtutorial
Name Blob Type Blob Tier Length Content Type Last Modified Snapshot
------------ ----------- ----------- -------- -------------- ------------------------- ----------
testfile.txt BlockBlob Hot 25 text/plain 2024-03-10T18:07:21+00:00


```

### What's next?

Try out some of the other quick tutorials to learn about how to use ClientIntents to manage network policies, Istio policies, PostgreSQL access, and more. You can use a single ClientIntents resource to specify all the access required for a pod.

## Teardown

To remove the deployed examples run:
```bash
kubectl delete namespace otterize-tutorial-azure-iam
```

To delete the Azure blob storage account & container:
```bash
az storage account delete --name $STORAGE_ACCOUNT_NAME --resource-group $RESOURCE_GROUP
```

To delete the cluster, if you created the one in this tutorial:
```bash
az aks delete --name $AKS_CLUSTER_NAME --resource-group $RESOURCE_GROUP
```
Loading
Loading