AKS AAD Pod Identity, JDBC
Let's do a quick one... Maybe. Goals:
- Mimic Active Directory Integrated Authentication in Azure Kubernetes
- Assign Azure Managed Identity to one or more Kubernetes pods
- Connect to Azure SQL (or SQL MI) without username/password
I've had a hard time finding all the right answers for Azure Kubernetes to connect to an Azure SQL (or MI). I've found a few minor errors in Azure documentation and most guides are not based on Azure's Preview ADD Pod Identity but is rather based on the opensource project that is the foundation of AKS AAD Pod Identity. So here's a quick snippet of commands to help others and my future self. Note that due to the Preview nature of these features, procedures and functionality may change.
Following is for converting from a cluster using Service Principals. Skip the conversion portion if your cluster is already set up with Managed Identity. WARNING! There seems to be an issue with conversion from SP to MI: https://github.com/Azure/AKS/issues/2094
https://docs.microsoft.com/en-us/azure/aks/use-azure-ad-pod-identity
NOTE: Max 50 identities per cluster. Developers appears to have added this arbitrary limit for the Azure feature preview period. I expect it to be lifted as it gets closer to being production ready. https://github.com/Azure/aad-pod-identity/issues/889
Set variables
Enter desired variables below.
export CLUSTER_RESOURCE_GROUP='<aks_resource_group_name>'
export CLUSTER_NAME='<aks_cluster_name>'
export IDENTITY_RESOURCE_GROUP='<identity_resource_group_name>'
export POD_IDENTITY_NAMESPACE='<kube_namespace>'
export IDENTITY_NAME='<identity_name>'
export POD_IDENTITY_NAME=$IDENTITY_NAME
Convert existing cluster to Managed Identity
WARNING!!! This seems to have some unwanted consequences. https://github.com/Azure/AKS/issues/2094
If you are using Service Principal for the cluster currently, you must now convert it to Managed Identity. We start by enabling the Preview feature.
NOTE: Azure doc enables UserAssignedIdentityPreview. We don't need this as we don't plan on using our own Managed Identity but rather just let AKS manage it.
az feature register --name MigrateToMSIClusterPreview --namespace Microsoft.ContainerService
az provider register -n Microsoft.ContainerService
az aks update -g ${CLUSTER_RESOURCE_GROUP} -n ${CLUSTER_NAME} --enable-managed-identity
az aks show -g ${CLUSTER_RESOURCE_GROUP} -n ${CLUSTER_NAME} --query "identity"
A node image update is needed. Before doing so, check for any updates to node image. If there's a newer image, the upgrade command will cause a restart of pods on nodes, but in so doing, will force cluster to start using Managed Identity. Azure's feature preview documentation does not mention another way to do so.
During my testing, this upgrade can be postponed for a suitable time. Pod Identity will function correctly. However, the cluster will still use Service Principal to manage other Azure resources it requests.
Following will show info of existing image, and available node image.
az aks nodepool show --name agentpool --cluster-name ${CLUSTER_NAME} -g ${CLUSTER_RESOURCE_GROUP} --query nodeImageVersion
az aks nodepool get-upgrades --nodepool-name agentpool --cluster-name ${CLUSTER_NAME} -g ${CLUSTER_RESOURCE_GROUP}
If there is a difference, you may now run the upgrade command. Again, this may cause pods to restart, so plan ahead.
az aks nodepool upgrade -g ${CLUSTER_RESOURCE_GROUP} --cluster-name ${CLUSTER_NAME} -n agentpool --node-image-only
Grant Permission to Azure Resources
(OPTIONAL) Now that Managed Identity is active, it will be wise to start granting access to resources such as a subnet to which Kubernetes may use for internal load balancer.
You may either use the "az role assignment create" command or assign access via Azure portal. The Managed Identity of the cluster has the same name as the cluster itself.
Enable Pod Identity Feature
az feature register --name EnablePodIdentityPreview --namespace Microsoft.ContainerService
az provider register -n Microsoft.ContainerService
az aks update -g ${CLUSTER_RESOURCE_GROUP} -n ${CLUSTER_NAME} --enable-pod-identity
This should create an nmi pod per cluster node to handle MSI auth interception.
Create an Azure Managed Identity
az identity create --resource-group ${IDENTITY_RESOURCE_GROUP} --name ${IDENTITY_NAME}
export IDENTITY_CLIENT_ID="$(az identity show -g ${IDENTITY_RESOURCE_GROUP} -n ${IDENTITY_NAME} --query clientId -otsv)"
export IDENTITY_RESOURCE_ID="$(az identity show -g ${IDENTITY_RESOURCE_GROUP} -n ${IDENTITY_NAME} --query id -otsv)"
Add a Pod Identity in K8s Cluster
az aks pod-identity add --resource-group ${CLUSTER_RESOURCE_GROUP} --cluster-name ${CLUSTER_NAME} --namespace ${POD_IDENTITY_NAMESPACE} --name ${POD_IDENTITY_NAME} --identity-resource-id ${IDENTITY_RESOURCE_ID}
kubectl describe azureidentities ${POD_IDENTITY_NAME} -n ${POD_IDENTITY_NAMESPACE}
Note that in the event this fails, I've found that the standard 30 second wait time in this command may not be long enough to automatically apply IAM permissions for the cluster's Managed Identity (name of cluster) to operate the created Managed Identity above. To avoid this rare occurrence, grant "Managed Identity Operator" role to the "IDENTITY_RESOURCE_GROUP".
Add a Pod Identity Binding
https://docs.microsoft.com/en-us/azure/aks/use-azure-ad-pod-identity#run-a-sample-application
JDBC Connection URL
The following is what we required for the application. The key is "authentication=ActiveDirectoryMSI". This will results in the NMI system pods to intercept authentication transmission, redirect it and return the appropriate authentication token to JDBC driver, allowing authentication without the need to supplying username/password.
jdbc:sqlserver://azcc-devdb.database.windows.net:1433;database=<database_name>;selectMethod=cursor;sendStringParametersAsUnicode=false;authentication=ActiveDirectoryMSI;encrypt=true;
Assuming you've granted access for the Managed Identity to the Azure SQL (or SQL MI) DB, this should allow you to now make the connection.