SPIRE

SPIRE 是 SPIFFE 规范的一个可用于生产环境的实现,它执行节点和工作负载的认证,以便在异构环境中安全地为运行的工作负载颁发加密身份。通过与 Envoy 的 SDS API 集成,可以将 SPIRE 配置为 Istio 工作负载的加密身份源。Istio 可以检测到实现了 Envoy SDS API 的 UNIX 域套接字的存在,并允许 Envoy 直接从其中通信并获取身份。

与默认的 Istio 身份管理相比,与 SPIRE 的集成提供了灵活的认证选项。例如,SPIRE 的插件架构使您可以选择 Kubernetes 命名空间和服务账户认证之外的多样化工作负载认证选项。SPIRE 的节点认证将认证扩展到工作负载所运行的物理或虚拟硬件上。

要了解关于如何将 SPIRE 与 Istio 集成的快速演示,请参阅通过 Envoy 的 SDS API 将 SPIRE 集成为 CA

请注意,此集成需要 istioctl 和数据平面均为 1.14 及更高版本。

此集成与 Istio 升级兼容。

安装 SPIRE

选项 1:快速开始

Istio 提供了一个基本的示例安装,可以快速启动 SPIRE:

Zip

  1. $ kubectl apply -f @samples/security/spire/spire-quickstart.yaml@

这将在您的集群中部署 SPIRE,以及下述两个附加组件:

选项 2:配置自定义 SPIRE 安装

请参阅 SPIRE 的 Kubernetes 快速入门指南 以开始将 SPIRE 部署到您的 Kubernetes 环境中。请参阅 SPIRE CA 集成先决条件 以获取有关如何配置 SPIRE 以与 Istio 部署集成的更多信息。

SPIRE CA 集成先决条件

要将您的 SPIRE 部署与 Istio 集成,需要配置 SPIRE:

  1. 访问 SPIRE 代理参考 并将 SPIRE 代理套接字路径配置为与 Envoy SDS 定义的套接字路径匹配。

    1. socket_path = "/run/secrets/workload-spiffe-uds/socket"
  2. 通过部署 SPIFFE CSI 驱动 与节点内的 Pod 共享 SPIRE 代理套接字,通过设置驱动程序的 -workload-api-socket-dir 参数来指定套接字目录的挂载位置。

请参阅 安装 Istio 以配置 Istio 以集成 SPIFFE CSI 驱动。

如果在 Istio 代理启动之前 SPIRE 尚未创建套接字,则 Istio 将成为 Envoy SDS 监听器。此时的时间由自定义 IstioOperator 控制。

安装 Istio

选项 1:使用 SPIRE Controller Manager 配置工作负载注册

通过部署 SPIRE Controller Manager 和 SPIRE 服务器,可以自动为与 ClusterSPIFFEID 自定义资源中定义的选择器匹配的每个新 Pod 进行注册。

必须在安装 Istio 之前应用 ClusterSPIFFEID。此外,必须配置 Ingress-gateway pod 以匹配 ClusterSPIFFEID 中定义的选择器。如果在安装期间未自动创建 Ingress Gateway 工作负载的注册条目,则工作负载将无法达到 Ready 状态。

  1. 创建 ClusterSPIFFEID 示例:

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: spire.spiffe.io/v1alpha1
    3. kind: ClusterSPIFFEID
    4. metadata:
    5. name: example
    6. spec:
    7. spiffeIDTemplate: "spiffe://{{ .TrustDomain }}/ns/{{ .PodMeta.Namespace }}/sa/{{ .PodSpec.ServiceAccountName }}"
    8. podSelector:
    9. matchLabels:
    10. spiffe.io/spire-managed-identity: "true"
    11. EOF

    示例 ClusterSPIFFEID 允许自动注册所有具有 spiffe.io/spire-managed-identity: "true" 标签的工作负载。对于具有此标签的 Pod,将提取 spiffeIDTemplate 中指定的值以形成 SPIFFE ID。

  2. 下载 Istio

  3. 创建具有自定义补丁的 Ingress Gateway 和 istio-proxy 的 Istio 配置。Ingress Gateway 组件包括 spiffe.io/spire-managed-identity: "true" 标签。

    1. $ cat <<EOF > ./istio.yaml
    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. # 这是用于自定义 sidecar 的模板
    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. readOnly: true
    28. components:
    29. ingressGateways:
    30. - name: istio-ingressgateway
    31. enabled: true
    32. label:
    33. istio: ingressgateway
    34. spiffe.io/spire-managed-identity: "true"
    35. k8s:
    36. overlays:
    37. - apiVersion: apps/v1
    38. kind: Deployment
    39. name: istio-ingressgateway
    40. patches:
    41. - path: spec.template.spec.volumes.[name:workload-socket]
    42. value:
    43. name: workload-socket
    44. csi:
    45. driver: "csi.spiffe.io"
    46. readOnly: true
    47. - path: spec.template.spec.containers.[name:istio-proxy].volumeMounts.[name:workload-socket]
    48. value:
    49. name: workload-socket
    50. mountPath: "/run/secrets/workload-spiffe-uds"
    51. readOnly: true
    52. - path: spec.template.spec.initContainers
    53. value:
    54. - name: wait-for-spire-socket
    55. image: busybox:1.28
    56. volumeMounts:
    57. - name: workload-socket
    58. mountPath: /run/secrets/workload-spiffe-uds
    59. readOnly: true
    60. env:
    61. - name: CHECK_FILE
    62. value: /run/secrets/workload-spiffe-uds/socket
    63. command:
    64. - sh
    65. - "-c"
    66. - |-
    67. echo "$(date -Iseconds)" Waiting for: ${CHECK_FILE}
    68. while [[ ! -e ${CHECK_FILE} ]] ; do
    69. echo "$(date -Iseconds)" File does not exist: ${CHECK_FILE}
    70. sleep 15
    71. done
    72. ls -l ${CHECK_FILE}
    73. EOF
  4. 应用配置:

    1. $ istioctl install --skip-confirmation -f ./istio.yaml
  5. 检查 Ingress-gateway Pod 状态:

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

    由于与之对应的注册条目已在 SPIRE 服务器上自动创建,Ingress-gateway pod 状态为 Ready。Envoy 能够从 SPIRE 获取加密身份。

请注意,在快速入门 部分中使用了 SPIRE Controller Manager

选项 2:手动工作负载注册

  1. 下载 Istio

  2. 部署 SPIRE到您的环境并确保所有部署都处于 Ready 状态后,配置 Istio ,包括对 Ingress-gateway 和 istio-proxy 的自定义补丁。

    创建 Istio 配置:

    1. $ cat <<EOF > ./istio.yaml
    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. # 这是用于自定义 sidecar 的模板
    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. readOnly: true
    28. components:
    29. ingressGateways:
    30. - name: istio-ingressgateway
    31. enabled: true
    32. label:
    33. istio: ingressgateway
    34. k8s:
    35. overlays:
    36. - apiVersion: apps/v1
    37. kind: Deployment
    38. name: istio-ingressgateway
    39. patches:
    40. - path: spec.template.spec.volumes.[name:workload-socket]
    41. value:
    42. name: workload-socket
    43. csi:
    44. driver: "csi.spiffe.io"
    45. readOnly: true
    46. - path: spec.template.spec.containers.[name:istio-proxy].volumeMounts.[name:workload-socket]
    47. value:
    48. name: workload-socket
    49. mountPath: "/run/secrets/workload-spiffe-uds"
    50. readOnly: true
    51. - path: spec.template.spec.initContainers
    52. value:
    53. - name: wait-for-spire-socket
    54. image: busybox:1.28
    55. volumeMounts:
    56. - name: workload-socket
    57. mountPath: /run/secrets/workload-spiffe-uds
    58. readOnly: true
    59. env:
    60. - name: CHECK_FILE
    61. value: /run/secrets/workload-spiffe-uds/socket
    62. command:
    63. - sh
    64. - "-c"
    65. - |-
    66. echo "$(date -Iseconds)" Waiting for: ${CHECK_FILE}
    67. while [[ ! -e ${CHECK_FILE} ]] ; do
    68. echo "$(date -Iseconds)" File does not exist: ${CHECK_FILE}
    69. sleep 15
    70. done
    71. ls -l ${CHECK_FILE}
    72. EOF
  3. 应用配置:

    1. $ istioctl install --skip-confirmation -f ./istio.yaml
  4. 检查 Ingress-gateway pod 状态:

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

    只有在 SPIRE 服务器上为 Ingress-gateway pod 和数据平面容器创建了相应的注册条目后,它们才会达到 Ready 状态。 接着,Envoy 将能够从 SPIRE 中获取加密身份信息。 请参阅注册工作负载以为您的网格中的服务注册条目。

Istio 配置与入口网关以及将要注入到工作负载 Pod 上的 Sidecar 共享 spiffe-csi-driver,从而使它们能够访问 SPIRE 代理的 UNIX 域套接字。

此配置还向网关添加了一个 initContainer,它将等待 SPIRE 创建 UNIX 域套接字,然后再启动 istio-proxy。 如果 SPIRE 代理尚未准备好,或者尚未使用相同的套接字路径正确配置,Ingress 网关的 initContainer 将永远处于等待状态。

注册工作负载

本节描述了在SPIRE服务器中注册工作负载的可用选项。

选项1:使用 SPIRE 控制器管理器进行注册

将为与 ClusterSPIFFEID自定义资源中定义的选择器匹配的每个新 Pod 自动注册新条目。 请参阅使用 SPIRE 控制器管理器进行工作负载注册的配置以获取示例 ClusterSPIFFEID 配置。

  1. 部署示例工作负载:

    Zip

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

    除了需要 spiffe.io/spire-managed-identity 标签之外,工作负载还需要使用 SPIFFE CSI 驱动器卷来访问 SPIRE 代理套接字。为了实现这一点,您可以利用安装 Istio 部分中的 spire Pod 注解模板,或者将 CSI 卷添加到您的工作负载的部署规范中。这两种方法都在下面的示例片段中进行了突出显示:

    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. spiffe.io/spire-managed-identity: "true"
    15. # Injects custom sidecar template
    16. annotations:
    17. inject.istio.io/templates: "sidecar,spire"
    18. spec:
    19. terminationGracePeriodSeconds: 0
    20. serviceAccountName: sleep
    21. containers:
    22. - name: sleep
    23. image: curlimages/curl
    24. command: ["/bin/sleep", "3650d"]
    25. imagePullPolicy: IfNotPresent
    26. volumeMounts:
    27. - name: tmp
    28. mountPath: /tmp
    29. securityContext:
    30. runAsUser: 1000
    31. volumes:
    32. - name: tmp
    33. emptyDir: {}
    34. # CSI volume
    35. - name: workload-socket
    36. csi:
    37. driver: "csi.spiffe.io"
    38. readOnly: true

请参阅验证为工作负载创建的身份 以检查已颁发的身份。

请注意,在快速入门部分中使用了SPIRE控制器管理器

选项 2:手动注册

为提高工作负载的认证安全性和稳健性,SPIRE 能够根据不同参数的一组选择器值来进行验证。 如果您是参照快速入门中的步骤来安装 SPIRE,则可以跳过这些步骤, 因为 SPIRE 使用自动注册的机制。

  1. 使用一组选择器为 Ingress Gateway 生成条目,例如 Pod 名称和 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. 获取 spire-server pod:

    1. $ SPIRE_SERVER_POD=$(kubectl get pod -l app=spire-server -n spire -o jsonpath="{.items[0].metadata.name}")
  3. 为节点上运行的 SPIRE 代理注册一个条目:

    1. $ kubectl exec -n spire "$SPIRE_SERVER_POD" -- \
    2. /opt/spire/bin/spire-server entry create \
    3. -spiffeID spiffe://example.org/ns/spire/sa/spire-agent \
    4. -selector k8s_psat:cluster:demo-cluster \
    5. -selector k8s_psat:agent_ns:spire \
    6. -selector k8s_psat:agent_sa:spire-agent \
    7. -node -socketPath /run/spire/sockets/server.sock
    8. Entry ID : d38c88d0-7d7a-4957-933c-361a0a3b039c
    9. SPIFFE ID : spiffe://example.org/ns/spire/sa/spire-agent
    10. Parent ID : spiffe://example.org/spire/server
    11. Revision : 0
    12. TTL : default
    13. Selector : k8s_psat:agent_ns:spire
    14. Selector : k8s_psat:agent_sa:spire-agent
    15. Selector : k8s_psat:cluster:demo-cluster
  4. 为 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. 部署示例工作负载:

    Zip

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

    请注意,工作负载需要使用 SPIFFE CSI 驱动器卷来访问 SPIRE 代理套接字。为了实现这一点,您可以利用安装 Istio部分中的 spire pod 注解模板,或者将 CSI 卷添加到您的工作负载的部署规范中。这两种方法都在下面的示例片段中进行了突出显示:

    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. inject.istio.io/templates: "sidecar,spire"
    17. spec:
    18. terminationGracePeriodSeconds: 0
    19. serviceAccountName: sleep
    20. containers:
    21. - name: sleep
    22. image: curlimages/curl
    23. command: ["/bin/sleep", "3650d"]
    24. imagePullPolicy: IfNotPresent
    25. volumeMounts:
    26. - name: tmp
    27. mountPath: /tmp
    28. securityContext:
    29. runAsUser: 1000
    30. volumes:
    31. - name: tmp
    32. emptyDir: {}
    33. # CSI volume
    34. - name: workload-socket
    35. csi:
    36. driver: "csi.spiffe.io"
    37. readOnly: true
  6. 获取 pod 信息:

    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. 注册工作负载:

    1. $ kubectl exec -n spire "$SPIRE_SERVER_POD" -- \
    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 ID 必须遵循 Istio SPIFFE ID 规范: spiffe://<trust.domain>/ns/<namespace>/sa/<service-account>

请参阅 SPIRE 注册工作负载的帮助文档,了解如何为工作负载创建新条目,并使用多个选择器进行认证以加强认证标准。

验证工作负载的身份是否已创建

请使用以下命令确认是否已为工作负载创建了身份:

  1. $ kubectl exec -t "$SPIRE_SERVER_POD" -n spire -c spire-server -- ./bin/spire-server entry show
  2. Found 2 entries
  3. Entry ID : c8dfccdc-9762-4762-80d3-5434e5388ae7
  4. SPIFFE ID : spiffe://example.org/ns/istio-system/sa/istio-ingressgateway-service-account
  5. Parent ID : spiffe://example.org/spire/agent/k8s_psat/demo-cluster/bea19580-ae04-4679-a22e-472e18ca4687
  6. Revision : 0
  7. X509-SVID TTL : default
  8. JWT-SVID TTL : default
  9. Selector : k8s:pod-uid:88b71387-4641-4d9c-9a89-989c88f7509d
  10. Entry ID : af7b53dc-4cc9-40d3-aaeb-08abbddd8e54
  11. SPIFFE ID : spiffe://example.org/ns/default/sa/sleep
  12. Parent ID : spiffe://example.org/spire/agent/k8s_psat/demo-cluster/bea19580-ae04-4679-a22e-472e18ca4687
  13. Revision : 0
  14. X509-SVID TTL : default
  15. JWT-SVID TTL : default
  16. Selector : k8s:pod-uid:ee490447-e502-46bd-8532-5a746b0871d6

检查 Ingress-gateway pod 状态:

  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

在为入口网关 pod 注册条目后,Envoy 将收到 SPIRE 颁发的身份并将其用于所有 TLS 和 mTLS 通信。

检查工作负载身份是否由 SPIRE 颁发

  1. 使用 istioctl proxy-config secret 命令检索 sleep 的 SVID 身份文档:

    1. $ istioctl proxy-config secret "$SLEEP_POD" -o json | jq -r \
    2. '.dynamicActiveSecrets[0].secret.tlsCertificate.certificateChain.inlineBytes' | base64 --decode > chain.pem
  2. 检查证书并确认 SPIRE 是颁发者:

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

SPIFFE 联邦

SPIRE 服务器能够对来自不同信任域的 SPIFFE 身份进行认证,这被称为 SPIFFE 联邦。

可以配置 SPIRE 代理通过 Envoy SDS API 向 Envoy 推送联邦捆绑包,从而使 Envoy 能够使用验证上下文来验证对等证书并信任来自另一个信任域的工作负载。 要使 Istio 能够通过 SPIRE 集成实现 SPIFFE 身份联合,请参阅 SPIRE 代理 SDS 配置,并为您的 SPIRE 代理配置文件设置以下 SDS 配置值。

配置描述资源名称
default_svid_name用于 Envoy SDS 的默认 X509-SVID 的 TLS 证书资源名称默认
default_bundle_name用于 Envoy SDS 的默认 X.509 bundle 的验证上下文资源名称
default_all_bundles_name用于 Envoy SDS 的所有 bundle(包括联邦的)的验证上下文资源名称ROOTCA
这将允许 Envoy 直接从 SPIRE 获取联邦 bundle。

创建联邦注册条目

  • 如果使用 SPIRE Controller Manager,请通过将 ClusterSPIFFEID CRfederatesWith 字段设置为您希望 pod 与之联邦的信任域来为工作负载创建联邦条目:

    1. apiVersion: spire.spiffe.io/v1alpha1
    2. kind: ClusterSPIFFEID
    3. metadata:
    4. name: federation
    5. spec:
    6. spiffeIDTemplate: "spiffe://{{ .TrustDomain }}/ns/{{ .PodMeta.Namespace }}/sa/{{ .PodSpec.ServiceAccountName }}"
    7. podSelector:
    8. matchLabels:
    9. spiffe.io/spire-managed-identity: "true"
    10. federatesWith: ["example.io", "example.ai"]
  • 要进行手动注册,请参阅为联邦创建注册条目

清理 SPIRE

如果您是通过 Istio 提供的快速入门 SPIRE 部署安装的 SPIRE,请使用以下命令来删除这些 Kubernetes 资源:

  1. $ kubectl delete CustomResourceDefinition clusterspiffeids.spire.spiffe.io
  2. $ kubectl delete CustomResourceDefinition clusterfederatedtrustdomains.spire.spiffe.io
  3. $ kubectl delete -n spire configmap spire-bundle
  4. $ kubectl delete -n spire serviceaccount spire-agent
  5. $ kubectl delete -n spire configmap spire-agent
  6. $ kubectl delete -n spire daemonset spire-agent
  7. $ kubectl delete csidriver csi.spiffe.io
  8. $ kubectl delete ValidatingWebhookConfiguration spire-controller-manager-webhook
  9. $ kubectl delete -n spire configmap spire-controller-manager-config
  10. $ kubectl delete -n spire configmap spire-server
  11. $ kubectl delete -n spire service spire-controller-manager-webhook-service
  12. $ kubectl delete -n spire service spire-server-bundle-endpoint
  13. $ kubectl delete -n spire service spire-server
  14. $ kubectl delete -n spire serviceaccount spire-server
  15. $ kubectl delete -n spire deployment spire-server
  16. $ kubectl delete clusterrole spire-server-cluster-role spire-agent-cluster-role manager-role
  17. $ kubectl delete clusterrolebinding spire-server-cluster-role-binding spire-agent-cluster-role-binding manager-role-binding
  18. $ kubectl delete -n spire role spire-server-role leader-election-role
  19. $ kubectl delete -n spire rolebinding spire-server-role-binding leader-election-role-binding
  20. $ kubectl delete namespace spire
  21. $ rm istio.yaml chain.pem