Service Principal

Use a Service Principal to access Keyvault.
Examples
  • SecretProviderClass
# This is a SecretProviderClass example using a service principal to access Key Vault
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: azure-kvname
spec:
  provider: azure
  parameters:
    usePodIdentity: "false"         # [OPTIONAL] if not provided, will default to "false"
    keyvaultName: "kvname"          # the name of the KeyVault
    cloudName: ""                   # [OPTIONAL for Azure] if not provided, azure environment will default to AzurePublicCloud
    objects:  |
      array:
        - |
          objectName: secret1
          objectType: secret        # object types: secret, key or cert
          objectVersion: ""         # [OPTIONAL] object versions, default to latest if empty
        - |
          objectName: key1
          objectType: key
          objectVersion: ""
    tenantID: "tid"                 # the tenant ID of the KeyVault
  • Pod yaml
# This is a sample pod definition for using SecretProviderClass and service-principal to access Key Vault
kind: Pod
apiVersion: v1
metadata:
  name: busybox-secrets-store-inline
spec:
  containers:
  - name: busybox
    image: registry.k8s.io/e2e-test-images/busybox:1.29-4
    command:
      - "/bin/sleep"
      - "10000"
    volumeMounts:
    - name: secrets-store-inline
      mountPath: "/mnt/secrets-store"
      readOnly: true
  volumes:
    - name: secrets-store-inline
      csi:
        driver: secrets-store.csi.k8s.io
        readOnly: true
        volumeAttributes:
          secretProviderClass: "azure-kvname"
        nodePublishSecretRef:                       # Only required when using service principal mode
          name: secrets-store-creds                 # Only required when using service principal mode

Configure Service Principal to access Keyvault

  1. Add your service principal credentials as a Kubernetes secrets accessible by the Secrets Store CSI driver. If using AKS you can learn about service principals in AKS here.

    A properly configured service principal will need to be passed in with the Service Principal’s appId and password. Ensure this service principal has all the required permissions to access content in your Azure Key Vault instance.

    # Client ID (AZURE_CLIENT_ID) will be the App ID of your service principal
    # Client Secret (AZURE_CLIENT_SECRET) will be the Password of your service principal
    
    kubectl create secret generic secrets-store-creds --from-literal clientid=<AZURE_CLIENT_ID> --from-literal clientsecret=<AZURE_CLIENT_SECRET>
    
    # Label the secret
    # Refer to https://secrets-store-csi-driver.sigs.k8s.io/load-tests.html for more details on why this is necessary in future releases.
    kubectl label secret secrets-store-creds secrets-store.csi.k8s.io/used=true
    

    The requirement for nodePublishSecretRef to be in the same namespace as the pod referencing it in volume is imposed by the Kubernetes core object type. In case of CSI Volumes, the nodePublishSecretRef is a LocalObjectReference which only accepts the name of the secret. The namespace is always defaulted to the pod namespace for the secret. In case of PersistentVolume the nodePublishSecretRef is a secretRef which accepts both name and namespace.

    If you do not have a service principal, run the following Azure CLI command to create a new service principal.

    # OPTIONAL: Create a new service principal, be sure to notate the SP secret returned on creation.
    az ad sp create-for-rbac --skip-assignment --name $SPNAME
    
    # If you lose your AZURE_CLIENT_SECRET (SP Secret), you can reset and receive it with this command:
    # az ad sp credential reset --name $SPNAME --credential-description "APClientSecret" --query password -o tsv
    

    With an existing service principal, assign the following permissions:

    # Set environment variables
    SPNAME=<servicePrincipalName>
    AZURE_CLIENT_ID=$(az ad sp show --id http://${SPNAME} --query appId -o tsv)
    KEYVAULT_NAME=<key-vault-name>
    KEYVAULT_RESOURCE_GROUP=<resource-group-name-for-KV>
    SUBID=<subscription-id>
    
    az keyvault set-policy -n $KEYVAULT_NAME --key-permissions get --spn $AZURE_CLIENT_ID
    az keyvault set-policy -n $KEYVAULT_NAME --secret-permissions get --spn $AZURE_CLIENT_ID
    az keyvault set-policy -n $KEYVAULT_NAME --certificate-permissions get --spn $AZURE_CLIENT_ID
    
  2. Update your deployment yaml to reference the service principal kubernetes secret created in the previous step

    If you did not change the name of the secret reference previously, no changes are needed.

    nodePublishSecretRef:
      name: secrets-store-creds
    

Pros

  1. Supported on both Windows and Linux.
  2. Supports Kubernetes clusters hosted in any cloud or on-premises.

Cons

  1. Service Principal credentials(client id & client secret) need to be created as a kubernetes Secret which is stored as plaintext in etcd.