승인 정책 개요

한 곳에서 실행될 수 있는 모놀리식 애플리케이션과 달리 글로벌 분산 마이크로서비스 앱은 네트워크 경계를 넘어 호출합니다. 즉, 애플리케이션에 더 많은 진입점이 있으며 악의적인 공격에 대한 기회가 많아집니다. Kubernetes 포드에는 일시적 IP가 있기 때문에 워크로드 간 액세스를 보호하려면 기존 IP 기반 방화벽 규칙은 적합하지 않습니다. 마이크로서비스 아키텍처에서는 새로운 보안 방식이 필요합니다. Kubernetes 서비스 계정 및 Istio 보안 정책, Cloud Service Mesh와 같은 보안 기능을 구축하면 애플리케이션을 보호할 수 있는 훨씬 더 많은 기능을 제공합니다.

이 페이지에서는 애플리케이션 작업자에게 AuthorizationPolicy 맞춤 리소스(CR)를 간략히 설명합니다. 승인 정책을 사용하면 애플리케이션(L7) 및 전송(L3/4) 레이어에서 워크로드의 액세스 제어를 사용 설정할 수 있습니다. 권한을 지정하려면 승인 정책을 구성합니다. 이 서비스 또는 사용자가 수행할 수 있는 작업은 무엇인가요?

승인 정책

메시의 서비스 간 요청 및 최종 사용자와 서비스 간 요청은 기본적으로 허용됩니다. AuthorizationPolicy CR을 사용하여 워크로드의 세분화된 정책을 정의합니다. 승인 정책을 적용하면 Cloud Service Mesh가 사이드카 프록시에 이를 배포합니다. 요청이 워크로드에 도달하면 사이드카 프록시는 승인 정책을 확인하여 요청 허용 또는 거부 여부를 결정합니다.

플랫폼에서 지원되는 AuthorizationPolicy CR의 필드에 관한 자세한 내용은 지원되는 기능을 참조하세요.

정책 범위

전체 서비스 메시, 네임스페이스 또는 개별 워크로드에 정책을 적용할 수 있습니다.

  • 메시 전체에 정책을 적용하려면 metadata:namespace 필드에 루트 네임스페이스 istio-system을 지정합니다.

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "mesh-wide"
      namespace: istio-system
    spec:
    ...
    
  • 네임스페이스에 정책을 적용하려면 metadata:namespace 필드에 네임스페이스를 지정합니다.

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "currencyservice"
      namespace: currencyservice
    spec:
    ...
    
  • 정책을 특정 워크로드로 제한하려면 selector 필드를 포함합니다.

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "frontend"
      namespace: demo
    spec:
      selector:
        matchLabels:
          app: frontend
       ...
    

기본 구조

승인 정책에는 정책 범위, actionrules의 목록이 포함됩니다.

  • 이전 섹션에서 설명한 대로 정책 범위는 전체 메시, 네임스페이스 또는 특정 워크로드일 수 있습니다. 이를 포함하는 경우 selector 필드는 정책 대상을 지정합니다.

  • action 필드는 요청의 ALLOW 또는 DENY 여부를 지정합니다. 작업을 지정하지 않으면 기본적으로 작업이 ALLOW로 설정됩니다. 명확성을 위해 항상 작업을 지정하는 것이 좋습니다. (승인 정책은 AUDITCUSTOM 작업도 지원합니다. AUDIT 작업은 일부 플랫폼에서만 지원됩니다. 자세한 내용은 지원되는 기능을 참조하세요.)

  • rules는 작업을 트리거할 시간을 지정합니다.

    • rulesfrom 필드는 요청의 소스를 지정합니다.

    • rulesto 필드는 요청의 작업을 지정합니다.

    • when 필드는 규칙을 적용하는 데 필요한 추가 조건을 지정합니다.

아래 예시를 참조하세요.

  • 정책은 demo 네임스페이스의 frontend 서비스 요청에 적용됩니다.

  • 'hello:world'가 요청 헤더에 있으면 요청이 허용되며, 그렇지 않은 경우 요청이 거부됩니다.

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "hello-world"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: frontend
  action: ALLOW
  rules:
  - when:
    - key: request.headers[hello]
      values: ["world"]

요청 작업에 대한 액세스 제어

rules 아래에 to 섹션을 추가하여 HTTP 메서드 또는 TCP 포트와 같은 특정 요청 작업에 대한 액세스를 제어할 수 있습니다. 다음 예시에서는 GETPOST HTTP 메서드만 demo 네임스페이스의 currencyservice에 허용됩니다.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: currencyservice
 namespace: demo
spec:
 selector:
   matchLabels:
     app: currencyservice
 action: ALLOW
 rules:
 - to:
   - operation:
       methods: ["GET", "POST"]

인증된 ID에 대한 액세스 제어

앞의 예시에서 정책은 인증되지 않은 워크로드의 요청을 허용합니다. STRICT 상호 TLS(mTLS)를 사용 설정한 경우 source 섹션에서 요청을 보낸 워크로드 또는 네임스페이스의 ID를 기반으로 액세스를 제한할 수 있습니다.

  • principals 또는 notPrincipal 필드를 사용하여 워크로드 수준에서 액세스를 제어할 수 있습니다.

  • namespaces 또는 notNamespaces 필드를 사용하여 네임스페이스 수준에서 액세스를 제어할 수 있습니다.

위의 모든 필드에서 STRICT mTLS가 사용 설정되어 있어야 합니다. STRICT mTLS를 설정할 수 없는 경우 대체 솔루션은 일반 텍스트 요청 거부를 참조하세요.

식별된 워크로드

다음 예시에서 currencyservice에 대한 요청은 frontend 서비스의 요청만 허용됩니다. 다른 워크로드의 currencyservice에 대한 요청이 거부됩니다.

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "currencyservice"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: currencyservice
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["example-project-1234.svc.id.goog/ns/demo/sa/frontend-sa"]

서비스 계정을 지정하려면 principals가 다음 형식이어야 합니다.

principals: ["PROJECT_ID.svc.id.goog/ns/NAMESPACE/sa/SERVICE_ACCOUNT_NAME"]

Citadel CA와 함께 클러스터 내 Cloud Service Mesh를 사용하는 경우 cluster.local이 트러스트 도메인입니다. 그 외의 경우에는 PROJECT_ID.svc.id.goog이 메시의 트러스트 도메인입니다.

식별된 네임스페이스

다음 예시는 소스가 foo 네임스페이스가 아니면 요청을 거부하는 정책을 보여줍니다.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin-deny
 namespace: foo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: DENY
 rules:
 - from:
   - source:
       notNamespaces: ["foo"]

값 일치

승인 정책의 필드 대부분은 다음과 같이 일치하는 스키마를 모두 지원합니다.

  • 완전 일치: 문자열이 완전히 일치합니다.
  • "*" 와일드 카드 문자를 사용한 와일드 카드 일치:
    • 프리픽스 일치: 끝이 "*"인 문자열입니다. 예를 들어 "test.example.*""test.example.com" 또는 "test.example.com.cn"과 일치합니다.
    • 서픽스 일치: "*"로 시작하는 문자열입니다. 예를 들어 "*.example.com""eng.example.com" 또는 "test.eng.example.com"과 일치합니다.
  • 존재 일치: 필드가 존재하고 비어 있지 않아야 한다고 지정하려면 fieldname: ["*"] 형식을 사용합니다. 이는 필드를 지정하지 않는 것과 다릅니다. 즉, 빈 필드를 포함하여 모든 항목이 일치합니다.

몇 가지 예외가 있습니다. 예를 들어 다음 필드는 완전 일치만 지원합니다.

  • when 섹션 아래의 key 필드
  • source 섹션 아래의 ipBlocks
  • to 섹션 아래의 ports 필드

다음 정책 예시에서는 프리픽스가 /test/* 또는 서픽스가 */info인 경로에서 액세스를 허용합니다.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: tester
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        paths: ["/test/*", "*/info"]

제외 일치

when 필드의 notValues, source 필드의 notIpBlocks, to 필드의 notPorts와 같은 부정 조건을 일치시키기 위해 Cloud Service Mesh는 제외 일치를 지원합니다. 다음 예시에서는 요청 경로가 /healthz가 아닌 경우 JWT 인증에서 파생된 유효한 요청 principals가 필요합니다. 따라서 정책은 JWT 인증에서 /healthz 경로에 대한 요청을 제외합니다.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: disable-jwt-for-healthz
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        notPaths: ["/healthz"]
    from:
    - source:
        requestPrincipals: ["*"]

일반 텍스트 요청 거부

Cloud Service Mesh에서는 자동 mTLS가 기본적으로 사용 설정됩니다. 자동 mTLS를 사용하면 클라이언트 사이드카 프록시가 서버에 사이드카가 있는지 자동으로 감지합니다. 클라이언트 사이드카는 mTLS를 사이드카가 있는 워크로드로 전송하고 일반 텍스트를 사이드카 없는 워크로드로 전송합니다. 최고의 보안을 위해 STRICT mTLS를 사용 설정하는 것이 좋습니다.

워크로드 또는 네임스페이스에 대해 STRICT 모드로 mTLS를 사용 설정할 수 없는 경우 다음을 수행할 수 있습니다.

  • namespaces 또는 principals가 비어 있지 않은 트래픽을 명시적으로 허용하는 승인 정책 만들기, 또는
  • namespaces 또는 principals가 비어 있는 트래픽 거부하기

namespacesprincipals는 mTLS 요청으로만 추출될 수 있으므로 이러한 정책은 모든 일반 텍스트 트래픽을 효과적으로 거부합니다.

다음 정책은 요청의 주 구성원이 비어 있는 경우 요청을 거부합니다(일반 텍스트 요청의 경우). 주 구성원이 비어 있지 않으면 정책이 요청을 허용합니다. ["*"]는 비어 있지 않은 일치를 의미하고, notPrincipals와 함께 사용한다는 것은 빈 주 구성원에 대한 일치를 의미합니다.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-mtls
  namespace: NAMESPACE
spec:
  action: DENY
  rules:
  - from:
    - source:
        notPrincipals: ["*"]

승인 정책 우선순위

별도의 ALLOWDENY 승인 정책을 구성할 수 있지만 정책이 원하는 대로 작동하는지 확인하려면 정책 우선순위 및 기본 동작을 이해해야 합니다. 다음 다이어그램은 정책 우선순위를 설명합니다.

승인 정책 우선순위

다음 섹션의 정책 예시에서는 여러 기본 동작과 이러한 동작이 유용할 수 있는 상황을 보여줍니다.

허용 안함

다음 예시에서는 일치하는 항목이 없는 ALLOW 정책을 보여줍니다. 기본적으로 다른 ALLOW 정책이 없으면 요청이 항상 거부됩니다.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-nothing
spec:
  action: ALLOW

allow-nopolicy 정책으로 시작하고 워크로드에 더 많은 액세스를 추가할 수 있도록 ALLOW 정책을 점진적으로 추가하는 것이 좋습니다.

모든 액세스 거부

다음 예시는 모든 항목과 일치하는 DENY 정책을 보여줍니다. DENY 정책은 ALLOW 정책보다 먼저 평가되므로 요청과 일치하는 ALLOW 정책이 있더라도 모든 요청이 거부됩니다.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
spec:
  action: DENY
  rules:
  - {}

모두 거부 정책은 워크로드에 대한 모든 액세스를 일시적으로 중지하려는 경우에 유용합니다.

모든 액세스 허용

다음 예시에서는 모든 항목과 일치하고 워크로드에 대한 전체 액세스를 허용하는 ALLOW 정책을 보여줍니다. allow-all 정책은 요청을 항상 허용하므로 다른 ALLOW 정책은 쓸모가 없습니다.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-all
spec:
  action: ALLOW
  rules:
  - {}

allow-all 정책은 워크로드에 일시적으로 전체 액세스 권한을 노출하려는 경우에 유용합니다. DENY 정책이 있으면 DENY 정책이 ALLOW 정책 이전에 평가되므로 요청이 계속 거부될 수 있습니다.

권장사항

  1. 각 서비스에 대해 Kubernetes 서비스 계정을 만들고 배포에서 서비스 계정을 지정합니다. 예를 들면 다음과 같습니다.

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: frontend-sa
      namespace: demo
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
      namespace:demo
    spec:
      selector:
        matchLabels:
          app: frontend
      template:
        metadata:
          labels:
            app: frontend
        spec:
          serviceAccountName: frontend-sa
        ...
    
  2. allow-nothing 정책으로 시작하고 점진적으로 ALLOW 정책을 추가하여 워크로드에 대한 액세스 권한을 늘립니다.

  3. 서비스에 JWT를 사용하는 경우:

    1. DENY 정책을 만들어 인증되지 않은 요청을 차단합니다. 예를 들면 다음과 같습니다.

      apiVersion: security.istio.io/v1beta1
      kind: AuthorizationPolicy
      metadata:
        name: requireJWT
        namespace: admin
      spec:
        action: DENY
        rules:
        -  from:
          - source:
              notRequestPrincipals: ["*"]
      
    2. allow-nothing 정책을 적용합니다.

    3. 각 워크로드의 ALLOW 정책을 정의합니다. 예시는 JWT 토큰을 참조하세요.

다음 단계

Cloud Service Mesh 보안 기능에 대해 자세히 알아보세요.

Istio 문서의 승인 정책에 대해 자세히 알아보세요.