Trust Domain Migration
This task shows you how to migrate from one trust domain to another without changing authorization policy.
In Istio 1.4, we introduce an alpha feature to support trust domain migration for authorization policy. This means if an Istio mesh needs to change its trust domain, the authorization policy doesn’t need to be changed manually. In Istio, if a workload is running in namespace foo with the service account bar, and the trust domain of the system is my-td, the identity of said workload is spiffe://my-td/ns/foo/sa/bar. By default, the Istio mesh trust domain is cluster.local, unless you specify it during the installation.
Before you begin
Before you begin this task, do the following:
Read the Istio authorization concepts.
Install Istio with a custom trust domain and mutual TLS enabled.
$ istioctl install --set profile=demo --set meshConfig.trustDomain=old-tdDeploy the httpbin sample in the
defaultnamespace and the sleep sample in thedefaultandsleep-allownamespaces:$ kubectl label namespace default istio-injection=enabled $ kubectl apply -f @samples/httpbin/httpbin.yaml@ $ kubectl apply -f @samples/sleep/sleep.yaml@ $ kubectl create namespace sleep-allow $ kubectl label namespace sleep-allow istio-injection=enabled $ kubectl apply -f @samples/sleep/sleep.yaml@ -n sleep-allowApply the authorization policy below to deny all requests to
httpbinexcept fromsleepin thesleep-allownamespace.$ kubectl apply -f - <<EOF apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: service-httpbin.default.svc.cluster.local namespace: default spec: rules: - from: - source: principals: - old-td/ns/sleep-allow/sa/sleep to: - operation: methods: - GET selector: matchLabels: app: httpbin --- EOFNotice that it may take tens of seconds for the authorization policy to be propagated to the sidecars.
Verify that requests to
httpbinfrom:sleepin thedefaultnamespace are denied.$ kubectl exec "$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})" -c sleep -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n" 403sleepin thesleep-allownamespace are allowed.$ kubectl exec "$(kubectl -n sleep-allow get pod -l app=sleep -o jsonpath={.items..metadata.name})" -c sleep -n sleep-allow -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n" 200
Migrate trust domain without trust domain aliases
Install Istio with a new trust domain.
$ istioctl install --set profile=demo --set meshConfig.trustDomain=new-tdRedeploy istiod to pick up the trust domain changes.
$ kubectl rollout restart deployment -n istio-system istiodIstio mesh is now running with a new trust domain,
new-td.Redeploy the
httpbinandsleepapplications to pick up changes from the new Istio control plane.$ kubectl delete pod --all$ kubectl delete pod --all -n sleep-allowVerify that requests to
httpbinfrom bothsleepindefaultnamespace andsleep-allownamespace are denied.$ kubectl exec "$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})" -c sleep -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n" 403$ kubectl exec "$(kubectl -n sleep-allow get pod -l app=sleep -o jsonpath={.items..metadata.name})" -c sleep -n sleep-allow -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n" 403This is because we specified an authorization policy that deny all requests to
httpbin, except the ones theold-td/ns/sleep-allow/sa/sleepidentity, which is the old identity of thesleepapplication insleep-allownamespace. When we migrated to a new trust domain above, i.e.new-td, the identity of thissleepapplication is nownew-td/ns/sleep-allow/sa/sleep, which is not the same asold-td/ns/sleep-allow/sa/sleep. Therefore, requests from thesleepapplication insleep-allownamespace tohttpbinwere allowed before are now being denied. Prior to Istio 1.4, the only way to make this work is to change the authorization policy manually. In Istio 1.4, we introduce an easy way, as shown below.
Migrate trust domain with trust domain aliases
Install Istio with a new trust domain and trust domain aliases.
$ cat <<EOF > ./td-installation.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: meshConfig: trustDomain: new-td trustDomainAliases: - old-td EOF $ istioctl install --set profile=demo -f td-installation.yaml -yWithout changing the authorization policy, verify that requests to
httpbinfrom:sleepin thedefaultnamespace are denied.$ kubectl exec "$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})" -c sleep -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n" 403sleepin thesleep-allownamespace are allowed.$ kubectl exec "$(kubectl -n sleep-allow get pod -l app=sleep -o jsonpath={.items..metadata.name})" -c sleep -n sleep-allow -- curl http://httpbin.default:8000/ip -sS -o /dev/null -w "%{http_code}\n" 200
Best practices
Starting from Istio 1.4, when writing authorization policy, you should consider using the value cluster.local as the trust domain part in the policy. For example, instead of old-td/ns/sleep-allow/sa/sleep, it should be cluster.local/ns/sleep-allow/sa/sleep. Notice that in this case, cluster.local is not the Istio mesh trust domain (the trust domain is still old-td). However, in authorization policy, cluster.local is a pointer that points to the current trust domain, i.e. old-td (and later new-td), as well as its aliases. By using cluster.local in the authorization policy, when you migrate to a new trust domain, Istio will detect this and treat the new trust domain as the old trust domain without you having to include the aliases.
Clean up
$ kubectl delete authorizationpolicy service-httpbin.default.svc.cluster.local $ kubectl delete deploy httpbin; kubectl delete service httpbin; kubectl delete serviceaccount httpbin $ kubectl delete deploy sleep; kubectl delete service sleep; kubectl delete serviceaccount sleep $ istioctl uninstall --purge -y $ kubectl delete namespace sleep-allow istio-system $ rm ./td-installation.yaml