SPIRE

    This integration with SPIRE provides flexible attestation options not available with the default Istio identity management while harnessing Istio’s powerful service management. For example, SPIRE’s plugin architecture enables diverse workload attestation options beyond the Kubernetes namespace and service account attestation offered by Istio. SPIRE’s node attestation extends attestation to the physical or virtual hardware on which workloads run.

    For a quick demo of how this SPIRE integration with Istio works, see Integrating SPIRE as a CA through Envoy’s SDS API.

    Note that this integration requires version 1.14 for both and the data plane.

    The integration is compatible with Istio upgrades.

    Istio provides a basic sample installation to quickly get SPIRE up and running:

    This will deploy SPIRE into your cluster, along with two additional components: the SPIFFE CSI Driver — used to share the SPIRE Agent’s UNIX Domain Socket with the other pods throughout the node — and the , a facilitator that performs automatic workload registration within Kubernetes. See Install Istio to configure Istio and integrate with the SPIFFE CSI Driver.

    Option 2: Configure a custom SPIRE installation

    See the SPIRE’s Quick start for Kubernetes guide to get started deploying SPIRE into your Kubernetes environment. See for more information on configuring SPIRE to integrate with Istio deployments.

    SPIRE CA Integration Prerequisites

    To integrate your SPIRE deployment with Istio, configure SPIRE:

    1. Access the and configure the SPIRE Agent socket path to match the Envoy SDS defined socket path.

      1. socket_path = "/run/secrets/workload-spiffe-uds/socket"
    2. Share the SPIRE Agent socket with the pods within the node by deploying the SPIFFE CSI Driver.

    See to configure Istio to integrate with the SPIFFE CSI Driver.

    Note that you must deploy SPIRE before installing Istio into your environment so that Istio can detect it as a CA.

    Install Istio

    1. .

      1. $ istioctl install --skip-confirmation -f - <<EOF
      2. apiVersion: install.istio.io/v1alpha1
      3. kind: IstioOperator
      4. metadata:
      5. namespace: istio-system
      6. spec:
      7. profile: default
      8. meshConfig:
      9. trustDomain: example.org
      10. values:
      11. global:
      12. # This is used to customize the sidecar template
      13. sidecarInjectorWebhook:
      14. templates:
      15. spire: |
      16. spec:
      17. containers:
      18. - name: istio-proxy
      19. volumeMounts:
      20. - name: workload-socket
      21. mountPath: /run/secrets/workload-spiffe-uds
      22. readOnly: true
      23. volumes:
      24. - name: workload-socket
      25. csi:
      26. driver: "csi.spiffe.io"
      27. components:
      28. ingressGateways:
      29. - name: istio-ingressgateway
      30. enabled: true
      31. label:
      32. istio: ingressgateway
      33. k8s:
      34. overlays:
      35. - apiVersion: apps/v1
      36. kind: Deployment
      37. name: istio-ingressgateway
      38. patches:
      39. - path: spec.template.spec.volumes.[name:workload-socket]
      40. value:
      41. csi:
      42. driver: "csi.spiffe.io"
      43. - path: spec.template.spec.containers.[name:istio-proxy].volumeMounts.[name:workload-socket]
      44. value:
      45. name: workload-socket
      46. mountPath: "/run/secrets/workload-spiffe-uds"
      47. readOnly: true
      48. EOF

      This will share the spiffe-csi-driver with the Ingress Gateway and the sidecars that are going to be injected on workload pods, granting them access to the SPIRE Agent’s UNIX Domain Socket.

    2. Use sidecar injection to inject the istio-proxy container into the pods within your mesh. See for information on how to apply the custom defined template into istio-proxy. This allows for the CSI driver to mount the UDS on the sidecars.

      Check Ingress-gateway pod state:

      1. $ kubectl get pods -n istio-system
      2. NAME READY STATUS RESTARTS AGE
      3. istio-ingressgateway-5b45864fd4-lgrxs 0/1 Running 0 17s
      4. istiod-989f54d9c-sg7sn 1/1 Running 0 23s

    Data plane containers will only reach Ready if a corresponding registration entry is created for them on the SPIRE Server. Then, Envoy will be able to fetch cryptographic identities from SPIRE. See Register workloads to register entries for services in your mesh.

    This section describes the options available for registering workloads in a SPIRE Server.

    By deploying along with a SPIRE Server, new entries are automatically registered for each new pod that is created.

    See Verifying that identities were created for workloads to check issued identities.

    Note that SPIRE workload registrar is used in the section.

    Option 2: Manual Registration

    To improve workload attestation security robustness, SPIRE is able to verify against a group of selector values based on different parameters. Skip these steps if you installed SPIRE by following the since it uses automatic registration.

    1. Generate an entry for an Ingress Gateway with a set of selectors such as the pod name and pod UID:

      1. $ INGRESS_POD=$(kubectl get pod -l istio=ingressgateway -n istio-system -o jsonpath="{.items[0].metadata.name}")
      2. $ INGRESS_POD_UID=$(kubectl get pods -n istio-system $INGRESS_POD -o jsonpath='{.metadata.uid}')
    2. Get the spire-server pod:

      1. $ SPIRE_SERVER_POD=$(kubectl get pod -l app=spire-server -n spire -o jsonpath="{.items[0].metadata.name}")
    3. Register an entry for the SPIRE Agent running on the node:

    4. Register an entry for the Ingress-gateway pod:

      1. $ kubectl exec -n spire $SPIRE_SERVER_POD -- \
      2. /opt/spire/bin/spire-server entry create \
      3. -spiffeID spiffe://example.org/ns/istio-system/sa/istio-ingressgateway-service-account \
      4. -parentID spiffe://example.org/ns/spire/sa/spire-agent \
      5. -selector k8s:sa:istio-ingressgateway-service-account \
      6. -selector k8s:ns:istio-system \
      7. -selector k8s:pod-uid:$INGRESS_POD_UID \
      8. -dns $INGRESS_POD \
      9. -dns istio-ingressgateway.istio-system.svc \
      10. -socketPath /run/spire/sockets/server.sock
      11. Entry ID : 6f2fe370-5261-4361-ac36-10aae8d91ff7
      12. SPIFFE ID : spiffe://example.org/ns/istio-system/sa/istio-ingressgateway-service-account
      13. Parent ID : spiffe://example.org/ns/spire/sa/spire-agent
      14. Revision : 0
      15. TTL : default
      16. Selector : k8s:ns:istio-system
      17. Selector : k8s:pod-uid:63c2bbf5-a8b1-4b1f-ad64-f62ad2a69807
      18. Selector : k8s:sa:istio-ingressgateway-service-account
      19. DNS name : istio-ingressgateway.istio-system.svc
      20. DNS name : istio-ingressgateway-5b45864fd4-lgrxs
    5. Deploy an example workload:

      1. $ istioctl kube-inject --filename @samples/security/spire/sleep-spire.yaml@ | kubectl apply -f -

      Note that the workload will need the SPIFFE CSI Driver volume to access the SPIRE Agent socket. To accomplish this, you can leverage the spire pod annotation template from the Install Istio section or add the CSI volume to the deployment spec of your workload. Both of these alternatives are highlighted on the example snippet below:

      1. apiVersion: apps/v1
      2. kind: Deployment
      3. metadata:
      4. name: sleep
      5. spec:
      6. replicas: 1
      7. selector:
      8. matchLabels:
      9. app: sleep
      10. template:
      11. metadata:
      12. labels:
      13. app: sleep
      14. # Injects custom sidecar template
      15. annotations:
      16. spec:
      17. terminationGracePeriodSeconds: 0
      18. serviceAccountName: sleep
      19. - name: sleep
      20. image: curlimages/curl
      21. command: ["/bin/sleep", "3650d"]
      22. imagePullPolicy: IfNotPresent
      23. volumeMounts:
      24. - name: tmp
      25. mountPath: /tmp
      26. securityContext:
      27. runAsUser: 1000
      28. volumes:
      29. - name: tmp
      30. emptyDir: {}
      31. # CSI volume
      32. - name: workload-socket
      33. csi:
      34. driver: "csi.spiffe.io"
    6. Get pod information:

      1. $ SLEEP_POD=$(kubectl get pod -l app=sleep -o jsonpath="{.items[0].metadata.name}")
      2. $ SLEEP_POD_UID=$(kubectl get pods $SLEEP_POD -o jsonpath='{.metadata.uid}')
    7. Register the workload:

      1. $ kubectl exec -n spire spire-server-0 -- \
      2. /opt/spire/bin/spire-server entry create \
      3. -spiffeID spiffe://example.org/ns/default/sa/sleep \
      4. -parentID spiffe://example.org/ns/spire/sa/spire-agent \
      5. -selector k8s:ns:default \
      6. -selector k8s:pod-uid:$SLEEP_POD_UID \
      7. -dns $SLEEP_POD \
      8. -socketPath /run/spire/sockets/server.sock

    SPIFFE IDs for workloads must follow the Istio SPIFFE ID pattern: spiffe://<trust.domain>/ns/<namespace>/sa/<service-account>

    See the to learn how to create new entries for workloads and get them attested using multiple selectors to strengthen attestation criteria.

    Verifying that identities were created for workloads

    Use the following command to confirm that identities were created for the workloads:

    Check the Ingress-gateway pod state:

    1. $ kubectl get pods -n istio-system
    2. NAME READY STATUS RESTARTS AGE
    3. istio-ingressgateway-5b45864fd4-lgrxs 1/1 Running 0 60s
    4. istiod-989f54d9c-sg7sn 1/1 Running 0 45s

    After registering an entry for the Ingress-gateway pod, Envoy receives the identity issued by SPIRE and uses it for all TLS and mTLS communications.

    1. Retrieve sleep’s SVID identity document using the istioctl proxy-config secret command:

      1. $ istioctl proxy-config secret $SLEEP_POD -o json | jq -r \
      2. '.dynamicActiveSecrets[0].secret.tlsCertificate.certificateChain.inlineBytes' | base64 --decode > chain.pem
    2. Inspect the certificate and verify that SPIRE was the issuer:

      1. $ openssl x509 -in chain.pem -text | grep SPIRE
      2. Subject: C = US, O = SPIRE, CN = sleep-5f4d47c948-njvpk

    SPIRE Servers are able to authenticate SPIFFE identities originating from different trust domains. This is known as SPIFFE federation.

    SPIRE Agent can be configured to push federated bundles to Envoy through the Envoy SDS API, allowing Envoy to use to verify peer certificates and trust a workload from another trust domain. To enable Istio to federate SPIFFE identities through SPIRE integration, consult SPIRE Agent SDS configuration and set the following SDS configuration values for your SPIRE Agent configuration file.

    This will allow Envoy to get federated bundles directly from SPIRE.

    Create federated registration entries

    • If using the SPIRE Kubernetes Workload Registrar, create federated entries for workloads by adding the pod annotation spiffe.io/federatesWith to the service deployment spec, specifying the trust domain you want the pod to federate with:

      1. podAnnotations:
      2. spiffe.io/federatesWith: "<trust.domain>"

    Cleanup SPIRE

    If you installed SPIRE using the quick start SPIRE deployment provided by Istio, use the following commands to remove those Kubernetes resources:

    1. $ kubectl delete CustomResourceDefinition spiffeids.spiffeid.spiffe.io
    2. $ kubectl delete -n spire serviceaccount spire-agent
    3. $ kubectl delete -n spire configmap spire-agent
    4. $ kubectl delete -n spire deployment spire-agent
    5. $ kubectl delete csidriver csi.spiffe.io
    6. $ kubectl delete -n spire configmap spire-server
    7. $ kubectl delete -n spire service spire-server
    8. $ kubectl delete -n spire serviceaccount spire-server
    9. $ kubectl delete -n spire statefulset spire-server
    10. $ kubectl delete clusterrole spire-server-trust-role spire-agent-cluster-role
    11. $ kubectl delete clusterrolebinding spire-server-trust-role-binding spire-agent-cluster-role-binding