Anthos Service Mesh의 보안 문제 해결

이 섹션에서는 일반적인 Anthos Service Mesh 문제와 해결 방법을 설명합니다. 추가 지원이 필요하면 지원 받기를 참조하세요.

Anthos Service Mesh에서 Mesh CA 또는 Istiod는 메시 내 모든 클러스터의 워크로드에 인증서를 발급합니다. 인증(예: mTLS) 및 승인 정책(예: 허용/거부)이 각 클러스터로 푸시됩니다. 이러한 정책은 통신할 수 있는 워크로드와 방법을 결정합니다.

TLS 문제

다음 섹션에서는 Anthos Service Mesh에서 TLS 관련 문제를 해결하는 방법을 설명합니다.

이 섹션의 예시에서는 클러스터에 액세스하는 데 사용하는 기본 Kubernetes 구성 파일의 컨텍스트 이름인 ${CTX} 변수를 사용합니다. ${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 인증서를 확인합니다. 이렇게 하려면 다음 단계를 따르세요.

  1. 수신하는 헤더를 표시할 수 있는 httpbin 샘플 서비스를 배포합니다.

  2. 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
  3. 또는 사이드카에서 openssl을 사용하여 전체 인증서 체인을 확인합니다.

    kubectl exec --context=${CTX} SOURCE_POD -n SOURCE_NAMESPACE -c istio-proxy \
    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를 사용하여 이러한 로그에서 오류를 찾을 수 있습니다.

이러한 오류는 일반적으로 정보 제공용이며 일시적입니다. 그러나 문제가 지속되는 경우 시스템에 문제가 있음을 나타낼 수 있습니다.

  1. istio-sidecar-injector MutatingWebhookConfiguration에 CA 번들이 있는지 확인합니다.

    자동 사이드카 삽입에 사용되는 사이드카 인젝터 웹훅에는 CA 번들이 API 서버 및 Istiod와의 보안 연결을 설정하도록 요구합니다. 이 CA 번들은 istiod의 구성에 패치되지만 경우에 따라 이를 덮어쓸 수도 있습니다(예: 웹훅 구성을 다시 적용하는 경우).

  2. CA 번들의 접속 상태를 확인합니다.

    kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io istio-sidecar-injector -o=jsonpath='{.webhooks[0].clientConfig.caBundle}'

    출력이 비어 있지 않으면 CA 번들이 구성된 것입니다. CA 번들이 없으면 istiod를 다시 시작하여 웹훅을 다시 스캔하도록 만들고 CA 번들을 다시 설치합니다.

승인 정책 거부 로깅

승인 정책은 요청이 정책에서 허용되지 않으면 요청을 거부합니다. HTTP(gRPC 포함) 프로토콜의 경우 상태 코드 403에 따라 요청이 거부됩니다. HTTP가 아닌 프로토콜의 경우 연결이 직접 종료됩니다. 승인 정책에 대한 자세한 내용은 Istio 승인을 참조하세요.

Google Cloud Observability 액세스 로그에는 승인 정책에 의해 요청이 거부될 때 필요한 정보가 포함되며 이 정보는 일부 상황에서 유용할 수 있습니다. 예를 들어 로그는 승인 정책에 따라 거부된 요청 수를 보여 주며, 백엔드 애플리케이션에서 거부를 유발한 정책 규칙을 확인하는 데 도움이 됩니다.

Google Cloud Observability 액세스 로그에는 승인 거부에 대한 다음 라벨이 포함됩니다.

  • response_details: 승인 정책으로 인해 거부가 발생하는 경우 AuthzDenied로 설정됩니다.
  • policy_name: 거부를 유발한 승인 DENY 정책의 네임스페이스와 이름이 포함됩니다. 값은 <Namespace>.<Name> 형식입니다. 예를 들어 foo.deny-method-getfoo 네임스페이스의 승인 정책 deny-method-get을 의미합니다.
  • policy_rule: 거부를 유발한 승인 정책 내 규칙의 색인이 포함됩니다. 예를 들어 0은 정책 내 첫 번째 규칙을 의미합니다.

액세스 로그를 가져오는 방법에 대한 자세한 내용은 Cloud Logging의 액세스 로그를 참조하세요.

승인 정책이 적용되지 않음

승인 정책이 시행되지 않는 경우 다음 명령어를 사용하여 확인합니다.

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 binding이 없거나 커스텀 리소스를 읽을 수 있는 RBAC 권한이 없을 때 발생할 수 있습니다.

  1. 계정에 IAM binding이 누락되었는지 확인합니다. 우선 사용자 인증 정보 및 권한 설정이 올바른지 확인합니다. 그런 후 다음 명령어를 사용하여 IAM binding이 있는지 확인합니다. 이 예시에서 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"
  2. RBAC 규칙이 올바르게 설치되었는지 확인합니다.

  3. RBAC 규칙이 없으면 istioctl install(또는 Anthos Service Mesh를 설치할 때 사용한 설치 방법)을 다시 실행하여 규칙을 다시 만듭니다.

  4. RBAC 규칙이 있고 오류가 지속되면 ClusterRoleBindingsRoleBindings가 RBAC 규칙을 올바른 Kubernetes 서비스 계정에 연결하는지 확인합니다. 또한 istiod 배포가 지정된 서비스 계정을 사용하는지 확인합니다.

Istiod 로그의 serverca 프로세스 오류

다음과 비슷한 오류가 표시될 수 있습니다.

Authentication failed: Authenticator ClientCertAuthenticator at index 0 got error

정규 표현식 문자열 /serverca.*Authentication failed:.*JWT/를 사용하여 이러한 로그에서 오류를 찾을 수 있습니다.

이 오류는 JWT 발급기관이 잘못 구성되거나, 클라이언트가 만료된 토큰을 사용하거나, 다른 보안 문제로 인해 연결이 istiod로 올바르게 인증되지 않는 경우 발생할 수 있습니다.