|
| 1 | +# Use AAD Pod Identity and Azure Managed Identity to access Azure SQL Server Database |
| 2 | + |
| 3 | +This extension project describes the steps for configuring the Claims Web API application to use **AAD Pod Identity** and **Managed Identity**. |
| 4 | + |
| 5 | +*AAD Pod Identity* enables Kubernetes applications to access cloud resources securely using managed identities and service principals. Without any code modifications, containerized applications can access any resource on Azure cloud that uses AAD as an Identity provider. |
| 6 | + |
| 7 | +*Managed Identity* makes applications more secure by eliminating secrets such as credentials in connection strings. |
| 8 | + |
| 9 | +In this extension project, you will work on completing the following tasks. |
| 10 | + |
| 11 | +- Deploy *AAD Pod Identity* components on AKS cluster |
| 12 | +- Configure Azure SQL Database to allow *Managed Identity** access to resources (eg., Tables) |
| 13 | +- Configure the Claims Web API application to retrieve data from Azure SQL Database Tables using Azure *Managed Identity* |
| 14 | + |
| 15 | +**Functional Diagram:** |
| 16 | + |
| 17 | +Refer to the architecture diagram [here](https://docs.microsoft.com/en-us/azure/aks/operator-best-practices-identity#use-pod-identities). |
| 18 | + |
| 19 | +**Prerequisites:** |
| 20 | +1. Readers are required to complete Sections A thru G in the [parent project](https://github.com/ganrad/aks-aspnet-sqldb-rest) before proceeding with the hands-on labs in this project. |
| 21 | + |
| 22 | +Readers are advised to refer to the following on-line resources as needed. |
| 23 | +- [Azure Active Directory] (https://docs.microsoft.com/en-us/azure/active-directory/) |
| 24 | +- [Azure AAD Pod Identity](https://github.com/Azure/aad-pod-identity) |
| 25 | +- [Managed Identities for Azure resources](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) |
| 26 | +- [Use Managed Identities in AKS](https://docs.microsoft.com/en-us/azure/aks/use-managed-identity) |
| 27 | + |
| 28 | +## A. Install AAD Pod Identity components on AKS Cluster |
| 29 | +**Approx. time to complete this section: 30 minutes** |
| 30 | + |
| 31 | +AAD Pod Identity consists of two key components and custom resources. The two core components are described below. |
| 32 | +- **Managed Identity Controller (MIC)** |
| 33 | + |
| 34 | + The MIC is a custom Kubernetes resource that watches for changes to Pods, Identities and Bindings through the Kubernetes API Server. When it detects a change, the MIC adds or deletes assigned identities as required. |
| 35 | +- **Node Managed Identity (NMI)** |
| 36 | + |
| 37 | + The NMI component is responsible for intercepting a Service Principal Token request sent by a Pod to an MSI endpoint, retrieving a matching Azure Identity from MIC and then making an [ADAL](https://docs.microsoft.com/en-us/azure/active-directory/azuread-dev/active-directory-authentication-libraries) request to get a token for the client id. The token is then returned to the Pod (FlexVolume driver). |
| 38 | + |
| 39 | +Follow the steps below to deploy AAD Pod Identity components and custom resources. |
| 40 | + |
| 41 | +1. (If you haven't already) Login into the Linux VM via SSH. |
| 42 | + |
| 43 | + ```bash |
| 44 | + # ssh into the VM. Substitute the public IP address for the Linux VM in the command below. |
| 45 | + |
| 46 | + # |
| 47 | + ``` |
| 48 | + |
| 49 | +2. Deploy MIC, NMI components and custom resources on the AKS cluster. |
| 50 | + |
| 51 | + ```bash |
| 52 | + # Deploy MIC, NMI components and custom resources for a non-RBAC enabled AKS cluster. |
| 53 | + # |
| 54 | + $ kubectl apply -f https://raw.githubusercontent.com/Azure/aad-pod-identity/master/deploy/infra/deployment.yaml |
| 55 | + # |
| 56 | + # For AKS Clusters, deploy the MIC and AKS add-on exception |
| 57 | + $ kubectl apply -f https://raw.githubusercontent.com/Azure/aad-pod-identity/master/deploy/infra/mic-exception.yaml |
| 58 | + # |
| 59 | + # Verify MIC (Deployments) and NMI (Daemon sets) pods have been deployed on the cluster. |
| 60 | + # The pods will be deployed in the 'default' namespace. There should be as many instances of |
| 61 | + # NMI pods running as there are nodes in the cluster (1 pod on each node). |
| 62 | + # |
| 63 | + $ kubectl get pods -n default -o wide |
| 64 | + # |
| 65 | + ``` |
| 66 | + |
| 67 | +3. Create an Azure Managed Identity in the **Node** Resource Group. |
| 68 | + |
| 69 | + Save the values of `clientId` and `id` from the command output. |
| 70 | + |
| 71 | + ```bash |
| 72 | + # Create a managed identity in the AKS 'Node' Resource Group. The resource group name should have a 'MC_' |
| 73 | + # prefix.. |
| 74 | + # Make sure you are logged in to your Azure account and have configured the correct subscription. |
| 75 | + # Substitute correct values for the following parameters: |
| 76 | + # - node-resource-group => Azure Kubernetes Service Node resource group |
| 77 | + # - name => Managed Identity name eg., claims-api-mid |
| 78 | + # |
| 79 | + $ az identity create -g <node-resource-group> -n <name> -o json |
| 80 | + # Important: Save the json output of the above command in a file !! We will need to use 'clientId', |
| 81 | + # 'id' and other values from the json output in the subsequent commands below. |
| 82 | + # |
| 83 | + ``` |
| 84 | + |
| 85 | +4. Assign Roles to AKS cluster Service Principal. |
| 86 | + |
| 87 | + Assign the AKS Service Principal, **Managed Identity Operator** and **Virtual Machine Contributor** roles for (scope of) the **Node** or **Cluster** Resource Group. |
| 88 | + |
| 89 | + ```bash |
| 90 | + # Retrieve the AKS cluster service principal id. |
| 91 | + # Substitute correct values for the following parameters: |
| 92 | + # - resource-group => Azure Kubernetes Service resource group |
| 93 | + # - name => AKS cluster name |
| 94 | + # |
| 95 | + $ az aks show -g <resource-group> -n <name> --query servicePrincipalProfile.clientId -o tsv |
| 96 | + # |
| 97 | + # Assign the 'Managed Identity Operator' role to the AKS cluster service principal on the |
| 98 | + # 'Node' resource group |
| 99 | + # Substitute correct values for the following parameters: |
| 100 | + # - sp-id => AKS Service Principal ID (output of previous command) |
| 101 | + # - subscription-id => Azure Subscription ID |
| 102 | + # - node-resource-group => Azure Kubernetes Service Node resource group |
| 103 | + # |
| 104 | + $ az role assignment create --role "Managed Identity Operator" --assignee <sp-id> --scope /subscriptions/<subscription-id>/resourcegroups/<node-resource-group> |
| 105 | + $ az role assignment create --role "Virtual Machine Contributor" --assignee <sp-id> --scope /subscriptions/<subscription-id>/resourcegroups/<node-resource-group> |
| 106 | + # |
| 107 | + ``` |
| 108 | + |
| 109 | +## B. Configure Azure SQL Database |
| 110 | +**Approx. time to complete this section: 45 minutes** |
| 111 | + |
| 112 | +To allow **Managed Identity** access to Azure SQL Database resources (eg., Tables), a managed identity user has to be created in the database and granted specific roles. This would allow the managed identity user to manipulate data in the database tables. |
| 113 | + |
| 114 | +1. Login to the Azure Portal. |
| 115 | + |
| 116 | + Login to the [Azure Portal](https://portal.azure.com) using your credentials. |
| 117 | + |
| 118 | +2. Configure Active Directory Admin account for Azure SQL Server. |
| 119 | + |
| 120 | + In order to create a managed identity **user** in Azure SQL, an Azure Active Directory **Account** is required. Use Azure Portal to set the AD Admin Account for Azure SQL by following the steps below. |
| 121 | + |
| 122 | + Access the Azure SQL Server instance and click on **Active Directory admin** blade as shown in the screenshot below |
| 123 | + |
| 124 | +  |
| 125 | + |
| 126 | + Click on **Set admin**. |
| 127 | + |
| 128 | + In the **Add admin** window, search for your AD Account Name and click **Select** as shown in the screenshot below. |
| 129 | + |
| 130 | +  |
| 131 | + |
| 132 | +3. Create Azure SQL Managed Identity User and Grant roles. |
| 133 | + |
| 134 | + In Azure SQL Server service, access the **SQL databases** blade and click on the **Database** name as shown below. |
| 135 | + |
| 136 | +  |
| 137 | + |
| 138 | + Select **Query editor** blade and then click on your account name under **Active Directory authentication** as shown in the screenshot below. |
| 139 | + |
| 140 | +  |
| 141 | + |
| 142 | + Run the following SQL-Transact commands in the **Query** panel/window. Click **Run**. |
| 143 | + |
| 144 | + ```bash |
| 145 | + # IMPORTANT: |
| 146 | + # Substitute the correct value for the managed identity name. |
| 147 | + # - managed-id-name => Managed Identity name eg., claims-api-mid. |
| 148 | + # |
| 149 | + CREATE USER [managed-id-name] FROM EXTERNAL PROVIDER; |
| 150 | + ALTER ROLE db_datareader ADD MEMBER [managed-id-name]; |
| 151 | + ALTER ROLE db_datawriter ADD MEMBER [managed-id-name]; |
| 152 | + ALTER ROLE db_ddladmin ADD MEMBER [managed-id-name]; |
| 153 | + GO |
| 154 | + ``` |
| 155 | + |
| 156 | + See screenshot below. |
| 157 | + |
| 158 | +  |
| 159 | + |
| 160 | +## C. Deploy AAD Pod Identity resoureces on AKS |
| 161 | + |
| 162 | +1. Create a new Kubernetes namespace for deploying Claims Web API application; |
| 163 | + |
| 164 | + ```bash |
| 165 | + # Create a new Kubernetes namespace 'dev-claims-mid' for deploying the Claims Web API application with |
| 166 | + # AAD Pod Identity and Managed Identity |
| 167 | + # |
| 168 | + $ kubectl create namespace dev-claims-mid |
| 169 | + # |
| 170 | + ``` |
| 171 | + |
| 172 | +2. Install Azure Pod Identity Kubernetes resource. |
| 173 | + |
| 174 | + This custom Kubernetes resource contains the ID's of the Azure Managed Identity. |
| 175 | + |
| 176 | + ```bash |
| 177 | + # Switch to the 'use-pod-identity-mid' directory. |
| 178 | + $ cd ./extensions/use-pod-identity-mid |
| 179 | + # |
| 180 | + # Edit the Pod Identity Kubernetes manifest file `./k8s-resources/azureIdentity.yaml`, update |
| 181 | + # values for the following two attributes and then save the file. |
| 182 | + # - ResourceID => 'id' attribute value of the managed identity created in Section A step 3 |
| 183 | + # - ClientID => 'clientId' value of the managed identity created in Section A step 3 |
| 184 | + # |
| 185 | + # Deploy the pod identity custom resource on AKS |
| 186 | + $ kubectl apply -f ./k8s-resources/azureIdentity.yaml -n dev-claims-mid |
| 187 | + # |
| 188 | + # Verify the Azure Identity resource got created in Kubernetes |
| 189 | + $ kubectl get azureidentity -n dev-claims-mid |
| 190 | + # |
| 191 | + ``` |
| 192 | + |
| 193 | +6. Install the Azure Pod Identity Binding Kubernetes resource. |
| 194 | + |
| 195 | + This custom Kubernetes resource binds the Claims Web API Pod (via the 'selector') with the Azure Managed Identity. |
| 196 | + |
| 197 | + ```bash |
| 198 | + # Deploy the pod identity binding custom resource on AKS |
| 199 | + $ kubectl apply -f ./k8s-resources/azureIdentityBinding.yaml -n dev-claims-mid |
| 200 | + # |
| 201 | + # Verify the Azure Identity Binding resource got created in Kubernetes |
| 202 | + $ kubectl get azureidentitybinding -n dev-claims-mid |
| 203 | + # |
| 204 | + ``` |
| 205 | + |
| 206 | +## E. Deploy the Claims Web API application |
| 207 | +**Approx. time to complete this section: 20 minutes** |
| 208 | + |
| 209 | +Execute the steps below to deploy the Claims Web API application on AKS. |
| 210 | + |
| 211 | +1. Update the Helm chart for the Claims Web API application. |
| 212 | + |
| 213 | + Update the Helm chart `./claims-api/values.yaml` file by referring to the table below. |
| 214 | + |
| 215 | + Parameter Name | Value | Description |
| 216 | + -------------- | ----- | ----------- |
| 217 | + image.repository | acr-name.azurecr.io/claims-api | Specify the ACR name and image name for the Claims Web API container image. |
| 218 | + image.tag | latest | Specify the claims-api image tag name. |
| 219 | + kv.secretName | sqldbconn | Specify the name of the Azure Key Vault **secret** containing the Azure SQL Database connection string. |
| 220 | + kv.resourceGroup | resource-group | Specify the name of the resource group containing the Azure Key Vault. |
| 221 | + kv.subscriptionId | subscription-id | Specify the Azure subscription in which the Key Vault is provisioned. |
| 222 | + kv.tenantId | tenant-id | Specify the AAD Tenant in which the Key Vault is provisioned. |
| 223 | + |
| 224 | + ```bash |
| 225 | + # (If you have not already) Switch to the 'use-pod-identity' extension directory. |
| 226 | + $ cd ./extensions/use-pod-identity |
| 227 | + # |
| 228 | + # Edit the './claims-api/values.yaml` file by referring to the table above. |
| 229 | + # |
| 230 | + ``` |
| 231 | + |
| 232 | +2. Deploy the Claims Web API application. |
| 233 | + |
| 234 | + ```bash |
| 235 | + # Use Helm to install the Claims Web API application in namespace 'dev-claims-podid' |
| 236 | + $ helm install ./claims-api/ --namespace dev-claims-podid --name claims-api-podid |
| 237 | + # |
| 238 | + # Verify the Claims Web API pod is running |
| 239 | + $ kubectl get pods -n dev-claims-podid |
| 240 | + # |
| 241 | + ``` |
| 242 | + |
| 243 | +3. Access the Claims Web API application. |
| 244 | + |
| 245 | + Retrieve the Public IP address of the Nginx ingress controller. See the command snippet below. |
| 246 | + |
| 247 | + ```bash |
| 248 | + # Get the ALB IP address for the Nginx Ingress Controller service. |
| 249 | + # The ALB Public IP address should be listed under column 'EXTERNAL-IP' in the command output. |
| 250 | + # |
| 251 | + $ kubectl get svc -n ingress-basic |
| 252 | + # |
| 253 | + ``` |
| 254 | + |
| 255 | + Access the Claims Web API service using a browser eg., http://[ALB Public IP]/api/v1/claims. |
| 256 | + |
| 257 | +Congrats! In this extension, you installed Azure **FlexVolume** driver and **AAD Pod Identity** components. Finally, you configured the Claims Web API application to use FlexVolume driver and the managed Pod Identity to retrieve SQL Connection String from an Azure Key Vault. |
0 commit comments