解决 Cloud Service Mesh 中的安全问题
本部分介绍常见的 Cloud Service Mesh 和 Istio API 问题,以及 解决方法。如果您需要其他帮助,请参阅获取支持。
在 Cloud Service Mesh 中,Cloud Service Mesh 证书授权机构或 Istiod 向网格中所有集群的工作负载颁发证书。身份验证(例如 mTLS)和授权政策(例如允许/拒绝)将被推送到每个集群。这些政策决定了哪些工作负载可以通信以及如何通信。
TLS 问题
以下部分介绍了如何解决 Cloud Service Mesh 中与 TLS 相关的问题。
本部分中的示例使用变量 ${CTX}
,作为上下文
输入
默认 Kubernetes 配置文件
供您用于访问集群的凭据。设置 ${CTX}
变量,如下例所示:
export CTX=gke_PROJECT_ID_CLUSTER_LOCATION_CLUSTER_NAME
验证传输层安全协议 (TLS) 是否强制执行
在服务需要使用 TLS 连接时,验证服务是否不允许使用纯文本请求:
kubectl exec SOURCE_POD -n SOURCE_NAMESPACE -c \ SOURCE_CONTAINER -- curl -v DESTINATION_URL
假设服务需要 TLS 连接,则上述纯文本请求应失败,从而产生如下所示的输出:
curl: (56) Recv failure: Connection reset by peer command terminated with exit code 56
检查 mTLS 证书
启用 mTLS 时,查看 X-Forwarded-Client-Cert
标头,检查工作负载的 mTLS 证书。为此,请执行以下步骤:
部署
httpbin
示例服务,它可以显示它收到的标头。使用
curl
查看X-Forwarded-Client-Cert
标头:kubectl exec --context=${CTX} SOURCE_POD -n SOURCE_NAMESPACE -c \ SOURCE_CONTAINER -- curl http://httpbin.sample:8000/headers -s | \ grep X-Forwarded-Client-Cert
X-Forwarded-Client-Cert
标头显示 mTLS 证书信息,如以下示例所示:X-Forwarded-Client-Cert": "By=spiffe://lt-multicluster-t2-5-15-2020.svc.id.goog/ns/sample/sa/httpbin;Hash=0781d68adfdab85b08b6758ed502f352464e81166f065cc6acde9433337b4494;Subject=\"OU=istio_v1_cloud_workload,O=Google LLC,L=Mountain View,ST=California,C=US\";URI=spiffe://lt-multicluster-t2-5-15-2020.svc.id.goog/ns/sample/sa/sleep
您也可以在 Sidecar 上使用
openssl
来查看完整证书链:kubectl debug --image istio/base --target istio-proxy -it --context=${CTX} SOURCE_POD \ -n SOURCE_NAMESPACE -- openssl s_client -alpn istio -showcerts -connect httpbin.sample:8000
输出将显示证书链。如果您使用的是 Mesh CA,请验证根证书 CN 是否包含
istio_v1_cloud_workload_root-signer-...
。如果您将 Istiod 用作证书授权机构,请验证根证书是否设置为O = <var>YOUR_TRUST_DOMAIN</var>
。
Istiod 日志中的 TLS bad certificate
错误
如果您在日志中看到 TLS 握手 bad certificate
错误,则说明 Istiod 可能无法与服务建立 TLS 连接。
您可以使用正则表达式字符串 TLS handshake error.*bad certificate
在日志中查找这些错误。
这些错误通常用于显示信息并且是暂时性的。不过,如果它们持续存在,则说明您的系统可能存在问题。
验证您的
istio-sidecar-injector
MutatingWebhookConfiguration
是否具有 CA 软件包。Sidecar 注入器 Webhook(用于自动执行 Sidecar 注入)需要使用 CA 软件包,以便与 API 服务器和 Istiod 建立安全连接。此 CA 软件包由 Istiod 修补到配置中,但有时可能会被覆盖(例如,如果您重新应用 Webhook 配置)。
验证 CA 软件包是否存在:
kubectl get mutatingwebhookconfiguration -l app=sidecar-injector -o=jsonpath='{.items[0].webhooks[0].clientConfig.caBundle}'
如果输出不为空,则说明 CA 软件包已配置。如果缺少 CA 软件包,请重启
istiod
以使其重新扫描 Webhook 并重新安装 CA 软件包。
授权政策拒绝日志记录
如需了解授权政策拒绝日志记录,请参阅拒绝日志记录。
授权政策未强制执行
如果您发现授权政策未强制执行,请使用以下命令进行验证:
kubectl exec --context=${CTX} -it SOURCE_POD -n SOURCE_NAMESPACE \ -c SOURCE_CONTAINER -- curl DESTINATION_URL
在输出中,access denied
消息表示授权政策已正确执行,如下所示:
RBAC: access denied
如果确认授权政策未强制执行,则系统会拒绝访问命名空间。以下示例拒绝访问名为 authz-ns
的命名空间:
kubectl apply --context=${CTX} -f - <<EOF apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: deny-authz-ns namespace: authz-ns spec: {} EOF
Istiod 日志中的“customresourcedefinitions.apiextensions.k8s.io is forbidden”错误
您可能会看到类似于以下内容的错误:
error failed to list CRDs: customresourcedefinitions.apiextensions.k8s.io is forbidden: User "system:serviceaccount:istio-system:istiod-service-account" cannot list resource "customresourcedefinitions" in API group "apiextensions.k8s.io" at the cluster scope
您可以使用正则表达式字符串 /error.*cannot list resource/
在日志中查找这些错误。
如果您的 Istiod 部署缺少正确的 IAM 绑定,或者 RBAC 权限不足,无法读取自定义资源,则可能会出现此错误。
检查您的账号中是否缺少 IAM 绑定。首先,请确保您已正确设置凭据和权限。然后,使用以下命令检查是否存在 IAM 绑定。在以下示例中,PROJECT_ID 是
gcloud config get-value project
的输出,PROJECT_NUMBER 是gcloud projects list --filter="project_id=${PROJECT_ID}" --format="value(project_number)"
的输出:gcloud projects add-iam-policy-binding ${PROJECT_ID} --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-meshdataplane.iam.gserviceaccount.com" --role "roles/meshdataplane.serviceAgent"
检查您的 RBAC 规则是否已正确安装。
如果缺少 RBAC 规则,请重新运行
asmcli install
以重新创建这些规则。如果存在 RBAC 规则并且错误仍然存在,请检查
ClusterRoleBindings
和RoleBindings
是否将 RBAC 规则附加到正确的 Kubernetes 服务账号。此外,请验证您的 Istiod 部署使用的是否是指定的服务账号。
Istiod 日志中的 serverca
进程错误
您可能会看到类似于以下内容的错误:
Authentication failed: Authenticator ClientCertAuthenticator at index 0 got error
您可以使用正则表达式字符串 /serverca.*Authentication failed:.*JWT/
在日志中查找这些错误。
如果 JWT 颁发者配置有误、客户端使用的是过期的令牌,或者存在其他某个安全问题导致连接无法向 Istiod 正确进行身份验证,则可能会出现此错误。