Azure Kubernetes Service (AKS) with Azure Key Vault (AKV) Part 1 — Secrets Store CSI

Step-By-Step Guidance

  1. Create an AKS resource: Create a resource group then an AKS cluster
  2. Create an AKV resource
az keyvault create -g <resource group name> -n <key vault name> --location <Ex: westus2, eastus...>
kubectl create ns <namespace name>
export SERVICE_PRINCIPAL_CLIENT_SECRET="$(az ad sp create-for-rbac --skip-assignment --name http://secrets-store-test --query 'password' -otsv)"export SERVICE_PRINCIPAL_CLIENT_ID="$(az ad sp show --id http://secrets-store-test --query 'appId' -otsv)"az keyvault set-policy -n <AKV name> --secret-permissions get --spn ${SERVICE_PRINCIPAL_CLIENT_ID}
# Create a secret with AAD SP client ID and secret
kubectl create secret generic secrets-store-creds --from-literal clientid=${SERVICE_PRINCIPAL_CLIENT_ID} --from-literal clientsecret=${SERVICE_PRINCIPAL_CLIENT_SECRET} -n <namespace name>
# Label the just-created secret
kubectl label secret secrets-store-creds secrets-store.csi.k8s.io/used=true
# Check whether the secret has been created in the environment
kubectl get secrets secrets-store-cred -n <namespace name>
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-out ingress-tls.crt \
-keyout ingress-tls.key \
-subj "/CN=demo.test.com/O=ingress-tls"
# export the a .pfx file with both .crt and .key
# skip Password prompt
openssl pkcs12 -export -in ingress-tls.crt -inkey ingress-tls.key -out <certificate name>.pfx

az keyvault certificate import --vault-name <AKV name> -n <certificate name> -f <certificate name>.pfx
# Check whether the certificate has been imported
az keyvault certificate list --vault-name <AKV name>
# the content of secretproviderclass.yaml
apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
name: azure-tls
spec:
provider: azure
secretObjects:
- secretName: ingress-tls-csi
type: kubernetes.io/tls
data:
- objectName: <certificate name>
key: tls.key
- objectName: <certificate name>
key: tls.crt
parameters:
usePodIdentity: "false"
keyvaultName: <AKV name> # the name of the KeyVault
objects: |
array:
- |
objectName: <certificate name>
objectType: secret
tenantId: <AAD tenant ID> # the tenant ID of the KeyVault
# create the secret provider class
kubectl apply -f secretproviderclass.yaml -n <namespace name>
# Check whether secretproviderclass has been created successfully
kubectl get secretproviderclasss -n <namespace name>
# add and HELM repo
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
# update HELM repo
helm repo update
# create the NGINX Ingress Controller with HELM
helm install ingress-nginx/ingress-nginx --generate-name \
--namespace <namespace name> \
--set controller.replicaCount=2 \
--set controller.nodeSelector."beta\.kubernetes\.io/os"=linux \
--set defaultBackend.nodeSelector."beta\.kubernetes\.io/os"=linux \
-f - <<EOF
controller:
extraVolumes:
- name: secrets-store-inline
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "azure-tls"
nodePublishSecretRef:
name: secrets-store-creds
extraVolumeMounts:
- name: secrets-store-inline
mountPath: "/mnt/secrets-store"
readOnly: true
EOF
# Check whether all related resources are up and running, especially the secret "ingress-tls-csi"
kubectl get deploy,pod,svc,ing,secret -n <namespace name>
# create app 1
kubectl apply -f https://raw.githubusercontent.com/Azure/secrets-store-csi-driver-provider-azure/5eff51f5a04b5e91db5c18080c30316a5dee772a/docs/sample/ingress-controller-tls/deployment-app-one.yaml -n <namespace name>
# create app 2
kubectl apply -f https://raw.githubusercontent.com/Azure/secrets-store-csi-driver-provider-azure/5eff51f5a04b5e91db5c18080c30316a5dee772a/docs/sample/ingress-controller-tls/deployment-app-two.yaml -n <namespace name>
# create Ingress
kubectl apply -f https://raw.githubusercontent.com/Azure/secrets-store-csi-driver-provider-azure/5eff51f5a04b5e91db5c18080c30316a5dee772a/docs/sample/ingress-controller-tls/ingress.yaml -n <namespace name>
# Check whether all related resources are up and running
kubectl get deploy,pod,svc,ing -n <namespace name>
# Get Ingress public IP address
kubectl get ing -n <namespace name>
# curl the service
curl -v -k --resolve demo.test.com:443:<public IP address> https://demo.test.com
Error from server (InternalError): error when creating "https://raw.githubusercontent.com/Azure/secrets-store-csi-driver-provider-azure/5eff51f5a04b5e91db5c18080c30316a5dee772a/docs/sample/ingress-controller-tls/ingress.yaml": Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": Post "https://ingress-nginx-1617752626-controller-admission.ingress-test.svc:443/networking/v1beta1/ingresses?timeout=10s": service "ingress-nginx-1617752626-controller-admission" not found
# Get Ingress service
kubectl get svc -n <namespace name>
# Get all ValidatingWebhookConfigurations
kubectl get ValidatingWebhookConfiguration -n <namespace name>
# Delete every ValidatingWebhookConfigurations that does not have the same naming convention you are seeing in Ingress service
kubectl delete ValidatingWebhookConfiguration -n <namespace name>

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Jonathan

Jonathan

Learning new things about Kubernetes every day. Hopefully, the learning notes could help people on the same journey!