Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ keywords: [security,certificate]
aliases:
- /docs/tasks/security/custom-ca-k8s/
owner: istio/wg-security-maintainers
test: no
test: yes
---

{{< boilerplate experimental >}}
Expand Down Expand Up @@ -36,64 +36,44 @@ Note that this example should only be used for basic evaluation. The use of the
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
pilot:
k8s:
env:
# Indicate to Istiod that we use an Custom Certificate Authority
- name: EXTERNAL_CA
value: ISTIOD_RA_KUBERNETES_API
# Tells Istiod to use the Kubernetes legacy CA Signer
- name: K8S_SIGNER
value: kubernetes.io/legacy-unknown
EOF
components:
pilot:
k8s:
env:
# Indicate to Istiod that we use an Custom Certificate Authority
- name: EXTERNAL_CA
value: ISTIOD_RA_KUBERNETES_API
# Tells Istiod to use the Kubernetes legacy CA Signer
- name: K8S_SIGNER
value: kubernetes.io/legacy-unknown
EOF
$ istioctl install --set profile=demo -f ./istio.yaml
{{< /text >}}

1. Deploy the `bookinfo` sample application in the bookinfo namespace.
Ensure that the following commands are executed in the Istio root directory.

{{< text bash >}}
$ kubectl create ns bookinfo
$ kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml) -n bookinfo
{{< /text >}}

### Verify that the certificates installed are correct

When the workloads are deployed, above, they send CSR Requests to Istiod which forwards them to the Kubernetes CA for signing.
If all goes well, the signed certificates are sent back to the workloads where they are then installed.
To verify that they have been signed by the Kubernetes CA, you need to first extract the signed certificates.

1. Dump all pods running in the namespace.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I notice you remove the installation of Bookinfo, but there is still an instruction below to follow the rest of the Bookinfo steps.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is an optional step, if the users want to explore mTLS with the custom ca signed certs. Are you suggesting that we add more detailed instructions/tests for this step? Or remove it?


{{< text bash >}}
$ kubectl get pods -n bookinfo
{{< /text >}}

Pick any one of the running pods for the next step.

1. Get the certificate chain and CA root certificate used by the Istio proxies for mTLS.

{{< text bash >}}
$ istioctl pc secret <pod-name> -o json > proxy_secret
$ ingress_pod="$(kubectl get pod -l app=istio-ingressgateway -n istio-system -o jsonpath="{.items[0].metadata.name}")"
$ istioctl pc secret "$ingress_pod".istio-system -o json | jq .dynamicActiveSecrets[1].secret.validationContext.trustedCa.inlineBytes | sed 's/\"//g' | base64 -d
{{< /text >}}

The proxy_secret json file contains the CA root certificate for mTLS in the `trustedCA` field. Note that this certificate is base64 encoded.

1. The certificate used by the Kubernetes CA (specifically the `kubernetes.io/legacy-unknown` signer) is loaded onto the secret associated with every service account in the bookinfo namespace.

{{< text bash >}}
$ kubectl get secrets -n bookinfo
$ secret="$(kubectl get secrets -n istio-system -o json | jq '.items[].metadata.name' | grep "account-token" | head -1 | sed 's/\"//g')"
$ kubectl get secret/"$secret" -n istio-system -o json | jq '.data."ca.crt"' | sed 's/\"//g' | base64 -d
{{< /text >}}

Pick a secret-name that is associated with any of the service-accounts. These have a "token" in their name.

{{< text bash >}}
$ kubectl get secrets -n bookinfo <secret-name> -o json
{{< /text >}}

The `ca.crt` field in the output contains the base64 encoded Kubernetes CA certificate.

1. Compare the `ca.cert` obtained in the previous step with the contents of the `TrustedCA` field in the step before. These two should be the same.

1. Compare the certs obtained from step 1 and step 2. These two should be the same.

1. (Optional) Follow the rest of the steps in the [bookinfo example](/docs/examples/bookinfo/) to ensure that communication between services is working as expected.

Expand Down Expand Up @@ -154,7 +134,7 @@ Refer to the [Kubernetes CSR documentation](https://kubernetes.io/docs/reference
namespace: istio-system
data:
root-cert.pem: <tls.cert from the step above>
EOF
EOF
$ kubectl apply -f external-ca-secret.yaml
{{< /text >}}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#!/bin/bash
# shellcheck disable=SC2034,SC2153,SC2155,SC2164

# Copyright Istio Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

####################################################################################################
# WARNING: THIS IS AN AUTO-GENERATED FILE, DO NOT EDIT. PLEASE MODIFY THE ORIGINAL MARKDOWN FILE:
# docs/tasks/security/cert-management/custom-ca-k8s/index.md
####################################################################################################

snip_deploying_istio_with_kubernetes_ca_1() {
cat <<EOF > ./istio.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
components:
pilot:
k8s:
env:
# Indicate to Istiod that we use an Custom Certificate Authority
- name: EXTERNAL_CA
value: ISTIOD_RA_KUBERNETES_API
# Tells Istiod to use the Kubernetes legacy CA Signer
- name: K8S_SIGNER
value: kubernetes.io/legacy-unknown
EOF
istioctl install --set profile=demo -f ./istio.yaml
}

snip_verify_that_the_certificates_installed_are_correct_1() {
ingress_pod="$(kubectl get pod -l app=istio-ingressgateway -n istio-system -o jsonpath="{.items[0].metadata.name}")"
istioctl pc secret "$ingress_pod".istio-system -o json | jq .dynamicActiveSecrets[1].secret.validationContext.trustedCa.inlineBytes | sed 's/\"//g' | base64 -d
}

snip_verify_that_the_certificates_installed_are_correct_2() {
secret="$(kubectl get secrets -n istio-system -o json | jq '.items[].metadata.name' | grep "account-token" | head -1 | sed 's/\"//g')"
kubectl get secret/"$secret" -n istio-system -o json | jq '.data."ca.crt"' | sed 's/\"//g' | base64 -d
}

snip_cleanup_part_1_1() {
kubectl delete ns istio-system
kubectl delete ns bookinfo
}

snip_deploy_custom_ca_controller_in_the_kubernetes_cluster_1() {
kubectl apply -f local-ca.yaml
}

snip_deploy_custom_ca_controller_in_the_kubernetes_cluster_2() {
kubectl get services -n signer-ca-system
}

! read -r -d '' snip_deploy_custom_ca_controller_in_the_kubernetes_cluster_2_out <<\ENDSNIP
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
signer-ca-controller-manager-metrics-service ClusterIP 10.8.9.25 none 8443/TCP 72s
ENDSNIP

snip_deploy_custom_ca_controller_in_the_kubernetes_cluster_3() {
kubectl get secrets signer-ca-5hff5h74hm -o json
}

snip_load_the_ca_root_certificate_into_a_secret_that_istiod_can_access_1() {
cat <<EOF > ./external-ca-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: external-ca-cert
namespace: istio-system
data:
root-cert.pem: <tls.cert from the step above>
EOF
kubectl apply -f external-ca-secret.yaml
}

snip_deploying_istio_1() {
cat <<EOF > ./istio.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
components:
base:
k8s:
overlays:
# Amend ClusterRole to add permission for istiod to approve certificate signing by custom signer
- kind: ClusterRole
name: istiod-istio-system
patches:
- path: rules[-1]
value: |
apiGroups:
- certificates.k8s.io
resourceNames:
# Name of k8s external Signer in this example
- example.com/foo
resources:
- signers
verbs:
- approve
pilot:
k8s:
env:
# Indicate to Istiod that we use an external signer
- name: EXTERNAL_CA
value: ISTIOD_RA_KUBERNETES_API
# Indicate to Istiod the external k8s Signer Name
- name: K8S_SIGNER
value: example.com/foo
overlays:
- kind: Deployment
name: istiod
patches:
- path: spec.template.spec.containers[0].volumeMounts[-1]
value: |
# Mount external CA certificate into Istiod
name: external-ca-cert
mountPath: /etc/external-ca-cert
readOnly: true
- path: spec.template.spec.volumes[-1]
value: |
name: external-ca-cert
secret:
secretName: external-ca-cert
optional: true
EOF
istioctl install --set profile=demo -f ./istio.yaml
}

snip_deploying_istio_2() {
kubectl create ns bookinfo
kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml) -n bookinfo
}

snip_verify_that_custom_ca_certificates_installed_are_correct_1() {
kubectl get pods -n bookinfo
}

snip_verify_that_custom_ca_certificates_installed_are_correct_2() {
istioctl pc secret <pod-name> -o json > proxy_secret
}

snip_cleanup_part_2_1() {
kubectl delete ns istio-system
kubectl delete ns bookinfo
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC2154

# Copyright Istio Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# shellcheck disable=SC2001

set -e
set -u
set -o pipefail

# @setup profile=none

echo y | snip_deploying_istio_with_kubernetes_ca_1

_wait_for_deployment istio-system istio
_wait_for_deployment istio-system istio-ingressgateway

_verify_same snip_verify_that_the_certificates_installed_are_correct_1 snip_verify_that_the_certificates_installed_are_correct_2

# @cleanup
snip_cleanup_1