Skip to content

Commit ce0b4f7

Browse files
committed
Added extension for managed identity integration
1 parent eec3123 commit ce0b4f7

File tree

13 files changed

+351
-3
lines changed

13 files changed

+351
-3
lines changed

Models/ClaimsContext.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
namespace ClaimsApi.Models {
33
public class ClaimsContext : DbContext {
44
public ClaimsContext(DbContextOptions<ClaimsContext> options) : base(options) {
5-
var conn = (Microsoft.Data.SqlClient.SqlConnection) Database.GetDbConnection();
6-
conn.AccessToken = (new Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider()).GetAccessTokenAsync("https://database.windows.net/").Result;
5+
/** var conn = (Microsoft.Data.SqlClient.SqlConnection) Database.GetDbConnection();
6+
conn.AccessToken = (new Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider()).GetAccessTokenAsync("https://database.windows.net/").Result; **/
77

88
}
99
public DbSet<ClaimItem> ClaimItems { get; set; }

appsettings.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
},
99
"AllowedHosts": "*",
1010
"ConnectionStrings": {
11-
"SqlServerDb": "Server=tcp:graksdb.database.windows.net,1433;Database=ClaimsDB;"
11+
"SqlServerDb": "Server=tcp:#{SQL_SRV_PREFIX}#.database.windows.net;Initial Catalog=ClaimsDB;Persist Security Info=False;User ID=#{SQL_USER_ID}#;Password=#{SQL_USER_PWD}#;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
1212
},
1313
"ApplicationInsights": {
1414
"InstrumentationKey": "<Instrumentation Key>"

extensions/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ The extensions below explore advanced features of AKS (Kubernetes) and additiona
99

1010
In this sub-project, secrets stored in Azure **Key Vault** are fetched and injected inside the Claims Web API application container at runtime. The project makes use of two open source projects - [AAD Pod Identity](https://github.com/Azure/aad-pod-identity) and [Azure Key Vault Kubernetes Flex Volume](https://github.com/Azure/kubernetes-keyvault-flexvol). Storing application secrets in Azure Key Vault provides a secure alternative to storing them in standard Kubernetes *Secret* API objects on the etcd server. The secrets stored in Key Vault never come to reside on the nodes and are directly injected into the application container at runtime.
1111

12+
- [Inject Azure Key Vault Secrets using AAD Pod Identity](./use-pod-identity)
13+
14+
In this sub-project, the Claims Web API application uses an Azure *Managed Identity* to access the Azure SQL Database. [Managed Identities for Azure Resources](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) is a feature of Azure Active Directory and can be used by Azure service instances (eg., AKS) to securely access other Azure resources (eg., Key Vault, SQL Server ...) that support AD authentication. With Managed Identity, applications deployed on Azure service instances need not store any credential information. This project also makes use of [AAD Pod Identity]((https://github.com/Azure/aad-pod-identity).
15+
1216
- [Explore advanced features of **Istio** Service Mesh](./istio-service-mesh)
1317

1418
This sub-project examines the advanced features supported by [Istio Service Mesh](https://istio.io/docs/concepts/what-is-istio/). Features such as intelligent request/traffic routing, traffic splitting (a.k.a Canary rollouts), request timeouts, circuit breaking, fault injection, secure intra-pod communication, rate limiting and others are explored in greater depth and detail.
+257
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
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+
![alt tag](./images/B-01.PNG)
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+
![alt tag](./images/B-02.PNG)
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+
![alt tag](./images/B-03.PNG)
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+
![alt tag](./images/B-04.PNG)
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+
![alt tag](./images/B-05.PNG)
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.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft": "Warning",
6+
"System": "Warning"
7+
}
8+
},
9+
"AllowedHosts": "*",
10+
"ConnectionStrings": {
11+
"SqlServerDb": "Server=tcp:graksdb.database.windows.net,1433;Database=ClaimsDB;"
12+
},
13+
"ApplicationInsights": {
14+
"InstrumentationKey": "<Instrumentation Key>"
15+
}
16+
}
Loading
Loading
78.7 KB
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: "aadpodidentity.k8s.io/v1"
2+
kind: AzureIdentity
3+
metadata:
4+
name: claims-api-mid
5+
spec:
6+
type: 0
7+
resourceID: "/subscriptions/0000-0000/resourcegroups/MC_rg_akscluster_region/providers/Microsoft.ManagedIdentity/userAssignedIdentities/claims-api-mid"
8+
clientID: "00000-22da-443d-8d79-0000"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: "aadpodidentity.k8s.io/v1"
2+
kind: AzureIdentityBinding
3+
metadata:
4+
name: claims-api-mid-binding
5+
spec:
6+
azureIdentity: claims-api-mid
7+
selector: claims-api-mid
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: claims-api-mid-deploy
5+
labels:
6+
app: claims-api
7+
spec:
8+
replicas: 1
9+
selector:
10+
matchLabels:
11+
app: claims-api
12+
template:
13+
metadata:
14+
labels:
15+
app: claims-api
16+
aadpodidbinding: claims-api-mid
17+
spec:
18+
containers:
19+
- name: claims-api-mid
20+
image: <acr-name>.azurecr.io/claims-api:<tag-name>
21+
imagePullPolicy: Always
22+
ports:
23+
- name: http
24+
containerPort: 80
25+
protocol: TCP
26+
readinessProbe:
27+
httpGet:
28+
path: /api/v1/claims/healthz
29+
port: http
30+
initialDelaySeconds:
31+
periodSeconds:
32+
livenessProbe:
33+
httpGet:
34+
path: /api/v1/claims/healthz
35+
port: http
36+
initialDelaySeconds: 10
37+
periodSeconds: 30
38+
nodeSelector:
39+
kubernetes.io/os: linux
40+
---
41+
apiVersion: v1
42+
kind: Service
43+
metadata:
44+
name: claims-api-mid-svc
45+
labels:
46+
app: claims-api
47+
spec:
48+
type: LoadBalancer
49+
ports:
50+
- port: 80
51+
targetPort: http
52+
protocol: TCP
53+
name: http
54+
selector:
55+
app: claims-api
56+

0 commit comments

Comments
 (0)