Note: SPIRE support is a new feature of Istio 1.14, please make sure to install Istio 1.14 and above.
Install Istio
to GitHub
Download the Istio installation package from above. After decompressing, it is recommended to use istioctl
install Istio.
istioctl install --set profile = demo
If you have an Istio version lower than 1.14 installed, please upgrade Istio first.
Install SPIRE
We use the quick installation method provided by Istio:
kubectl apply -f samples/security/spire/spire-quickstart.yaml
This will install the following components:
namespace/spire created csidriver.storage.k8s.io/csi.spiffe.io created customresourcedefinition.apiextensions.k8s.io/spiffeids.spiffeid.spiffe.io created clusterrolebinding.rbac.authorization.k8s.io/k8s-workload-registrar-role-binding created clusterrole.rbac.authorization.k8s.io/k8s-workload-registrar-role created configmap/k8s-workload-registrar created serviceaccount/spire-server created configmap/trust-bundle created clusterrole.rbac.authorization.k8s.io/spire-server-trust-role created clusterrolebinding.rbac.authorization.k8s.io/spire-server-trust-role-binding created configmap/spire-server created statefulset.apps/spire-server created service/spire-server created serviceaccount/spire-agent created clusterrole.rbac.authorization.k8s.io/spire-agent-cluster-role created clusterrolebinding.rbac.authorization.k8s.io/spire-agent-cluster-role-binding created configmap/spire-agent created daemonset.apps/spire-agent created
It needs to be patched so that all sidecars and ingresses can share the UNIX Domain Socket of SPIRE agent.
istioctl install --skip-confirmation -f - <<EOF apiVersion : install.istio.io/v1alpha1 kind : IstioOperator metadata : namespace : istio-system spec : profile : default meshConfig : trustDomain : example.org values : global : # This is used to customize the sidecar template sidecarInjectorWebhook : templates : spire : | spec: containers: - name: istio-proxy volumeMounts: - name: workload-socket mountPath: /run/secrets/workload-spiffe-uds readOnly: true volumes: - name: workload-socket csi: driver: "csi.spiffe.io" components : ingressGateways : - name : istio-ingressgateway enabled : true label : istio : ingressgateway k8s : overlays : - apiVersion : apps/v1 kind : Deployment name : istio-ingressgateway patches : - path : spec.template.spec.volumes.[name:workload-socket] value : name : workload-socket csi : driver : "csi.spiffe.io" - path : spec.template.spec.containers.[name:istio-proxy].volumeMounts.[name:workload-socket] value : name : workload-socket mountPath : "/run/secrets/workload-spiffe-uds" readOnly : true EOF
With Istio and SPIRE installed, we can register the payload.
Automatically register Kubernetes payloads
During the quick install of SPIRE, we already installed the SPRIE Kubernetes Workload Registrar
, which means that we have turned on automatic load registration. Now check to see if SPIRE issued an identity certificate to the payload.
kubectl exec -i -t spire-server-0 -n spire -c spire-server -- /bin/sh -c "bin/spire-server entry show -socketPath /run/spire/sockets/server.sock"
You will see results like the following:
# Node Entry ID : 3f17c8be-1379-4b7c-9a01-90805165d59f SPIFFE ID : spiffe://example.org/k8s-workload-registrar/demo-cluster/node/gke-jimmy-cluster-default-pool-d5041909-3atb Parent ID : spiffe://example.org/spire/server Revision : 0 TTL : default Selector : k8s_psat:agent_node_uid:cbab5123-b32f-49d0-89f2-0a7e4d2b0edd Selector : k8s_psat:cluster:demo-cluster # Ingress gateway Entry ID : ffc76b2e-e602-4ad3-8069-993ffbf4440e SPIFFE ID : spiffe://example.org/ns/istio-system/sa/istio-ingressgateway-service-account Parent ID : spiffe://example.org/k8s-workload-registrar/demo-cluster/node/gke-jimmy-cluster-default-pool-d5041909-0ucb Revision : 1 TTL : default Selector : k8s:node-name:gke-jimmy-cluster-default-pool-d5041909-0ucb Selector : k8s:ns:istio-system Selector : k8s:pod-uid:be32b10a-b5a4-4716-adaf-eab778f58c13 DNS name : istio-ingressgateway-6989cbc776-87qb6 DNS name : istio-ingressgateway.istio-system.svc # SPIRE Server Entry ID : 54444848-95ec-4b4d-a7c5-902a4049c96a SPIFFE ID : spiffe://example.org/ns/spire/sa/spire-server Parent ID : spiffe://example.org/k8s-workload-registrar/demo-cluster/node/gke-jimmy-cluster-default-pool-d5041909-0ucb Revision : 1 TTL : default Selector : k8s:node-name:gke-jimmy-cluster-default-pool-d5041909-0ucb Selector : k8s:ns:spire Selector : k8s:pod-uid:4917defc-9b5a-42d8-9b98-c0e0a48c0313 DNS name : spire-server-0 DNS name : spire-server.spire.svc
The parent ID of each node is spiffe://example.org/ns/spire/sa/spire-server
, and the parent of spiffe spiffe://example.org/ns/spire/sa/spire-server
is spiffe://example.org/k8s-workload-registrar/demo-cluster/node/gke-jimmy-cluster-default-pool-d5041909-0ucb
.
That is to say, the hierarchy of workloads is as follows:
-
SPIRE Server:
spiffe://example.org/spire/server
-
Kubernetes node:
spiffe://example.org/k8s-workload-registrar/demo-cluster/node/
-
Normal service account:
spiffe://example.org/{namespace}/spire/sa/{service_acount}
SPIRE creates SPIFFE IDs for workloads selected via a tag selector.
A workload’s SPIFEE ID is in the format spiffe://<trust.domain>/ns/<namespace>/sa/<service-account>
.
Deploy the application
Next we deploy an application, and then check that SPIRE is the identity it should provide.
Deploy the sample application sleep
provided by Istio with the following command:
istioctl kube-inject --filename samples/security/spire/sleep-spire.yaml | kubectl apply -f -
Because we patched when we installed Istio and made SPIRE automatic injection, then all pods will share the UNIX Domain Socket in SPIRE Agent: /run/secrets/workload-spiffe-uds/socket
. Getting the YAML of the running sleep
pod, we can see that it has a volume configured as follows:
volumes : - name : workload-socket csi : driver : csi.spiffe.io
and volumeMounts
as follows:
volumeMounts : - name : workload-socket readOnly : true mountPath : /run/secrets/workload-spiffe-uds - name : workload-socket mountPath : /var/run/secrets/workload-spiffe-uds - name : workload-certs mountPath : /var/run/secrets/workload-spiffe-credentials - name : istiod-ca-cert
This all confirms that the SPRIE Agent shares the UNIX Domain Socket with the workload pod.
Let’s query the SPIRE entry in the Kubernetes cluster again, and you will see that the sleep entry has been registered.
Entry ID : bd4457af-c55c-4d8c-aee2-4d477a79b465 SPIFFE ID : spiffe://example.org/ns/default/sa/sleep Parent ID : spiffe://example.org/k8s-workload-registrar/demo-cluster/node/gke-jimmy-cluster-default-pool-d5041909-3atb Revision : 1 TTL : default Selector : k8s:node-name:gke-jimmy-cluster-default-pool-d5041909-3atb Selector : k8s:ns:default Selector : k8s:pod-uid:81f116ce-6538-4492-a78a-98b163b58310 DNS name : sleep-9df96d88-tvl49 DNS name : sleep.default.svc
Check the SVID of sleep again.
istioctl proxy-config secret $SLEEP_POD -o json | jq -r \ '.dynamicActiveSecrets[0].secret.tlsCertificate.certificateChain.inlineBytes' | base64 --decode > chain.pem
The above command obtains the secret of Envoy in the sleep pod, parses the TLS certificate in it, decodes it base64 and saves it to the chain.pem
file.
openssl x509 -in chain.pem -text | grep SPIRE
Using OpenSSL to resolve the issuer, you will get the following result.
Subject: C = US, O = SPIRE, CN = sleep-9df96d88-tvl49
SPIFFE also supports federation. You can configure bundles for SPIRE Agent SDS. You also need to add the annotation spiffe.io/federatesWith: "<trust.domain>"
to the pod, and then Envoy will obtain the bundle from the SPRIE Server. For detailed steps, please refer to Istio official documentation
.
The above is the whole process of integrating SPIRE in Istio.
refer to
This article is reprinted from https://jimmysong.io/blog/how-to-integrate-spire-with-istio/
This site is for inclusion only, and the copyright belongs to the original author.