1.13. 보안

서비스 메시 애플리케이션이 복잡한 마이크로 서비스를 사용하여 구성된 경우 Red Hat OpenShift Service Mesh를 사용하여 해당 서비스 간 통신 보안을 사용자 지정할 수 있습니다.

사전 준비 사항

샘플 애플리케이션은 보안 개념을 설명하는 데 도움이 됩니다.

1.13.1.

일부 프로토콜(IKE, SSH)에서는 기본 인증 모드이며, 다른 프로토콜(TLS)에서는 선택적입니다. TLS는 서비스 메시 인프라와 두 사이드카 프록시 사이에서 전적으로 처리됩니다.

기본적으로 Red Hat OpenShift Service Mesh의 mTLS가 활성화되고 허용 모드로 설정됩니다. 여기서 서비스 메시의 사이드카는 일반 텍스트 트래픽과 mTLS를 사용하여 암호화된 연결을 모두 허용합니다. 메시의 서비스가 메시 외부 서비스와 통신하는 경우 엄격한 mTLS가 해당 서비스 간의 통신을 중단할 수 있습니다. 워크로드를 서비스 메시로 마이그레이션하는 동안 허용 모드를 사용합니다. 그러면 메시, 네임스페이스 또는 애플리케이션 전반에서 엄격한 mTLS를 활성화할 수 있습니다.

ServiceMeshControlPlane 리소스의 데이터 플레인 수준에서 메시의 네임스페이스를 보호할 수 있습니다. 트래픽 암호화 연결을 사용자 지정하려면 PeerAuthenticationDestinationRule 리소스를 사용하여 애플리케이션 수준에서 네임스페이스를 구성합니다.

1.13.1.1. 서비스 메시에서 엄격한 mTLS 활성화

워크로드가 외부 서비스와 통신하지 않으면 통신 중단 없이 메시 전체에서 mTLS를 빠르게 활성화할 수 있습니다. ServiceMeshControlPlane 리소스에서 spec.security.dataPlane.mtlstrue로 설정하여 활성화할 수 있습니다. Operator는 필요한 리소스를 생성합니다.

apiVersion: maistra.io/v2
kind: ServiceMeshControlPlane
spec:
  version: v2.3
  security:
    dataPlane:
      mtls: true

절차

  1. 웹 콘솔에 로그인합니다.
  2. Operators설치된 Operators를 클릭합니다.
  3. 제공된 API에서 Service Mesh Control Plane을 클릭합니다.
  4. ServiceMeshControlPlane 리소스의 이름(예: production)을 클릭합니다.
  5. 세부 정보 페이지에서 데이터 플레인 보안보안 섹션에서 토글을 클릭합니다.
1.13.1.1.1. 특정 서비스의 수신 연결에 대해 사이드카 구성

정책을 생성하여 개별 서비스 또는 네임스페이스에 대해 mTLS를 구성할 수도 있습니다.

절차

  1. 다음 예제를 사용하여 YAML 파일을 생성합니다.

    PeerAuthentication 정책 예 policy.yaml

    apiVersion: security.istio.io/v1beta1
    kind: PeerAuthentication
    metadata:
      name: default
      namespace: <namespace>
    spec:
      mtls:
        mode: STRICT

    1. <namespace>를 서비스가 있는 네임스페이스로 바꿉니다.
  2. 다음 명령을 실행하여 서비스가 있는 네임스페이스에 리소스를 생성합니다. 방금 생성한 정책 리소스의 namespace 필드와 일치해야 합니다.

    $ oc create -n <namespace> -f <policy.yaml>
참고

자동 mTLS를 사용하지 않고 PeerAuthentication을 STRICT으로 설정하는 경우 서비스에 대한 DestinationRule 리소스를 생성해야 합니다.

1.13.1.1.2. 발신 연결에 대한 사이드카 구성

메시에서 다른 서비스로 요청을 보낼 때 mTLS를 사용하도록 서비스 메시를 구성하는 대상 규칙을 생성합니다.

절차

  1. 다음 예제를 사용하여 YAML 파일을 생성합니다.

    DestinationRule 예제 destination-rule.yaml

    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: default
      namespace: <namespace>
    spec:
      host: "*.<namespace>.svc.cluster.local"
      trafficPolicy:
       tls:
        mode: ISTIO_MUTUAL

    1. <namespace>를 서비스가 있는 네임스페이스로 바꿉니다.
  2. 다음 명령을 실행하여 서비스가 있는 네임스페이스에 리소스를 생성합니다. 방금 생성한 DestinationRule 리소스의 namespace 필드와 일치해야 합니다.

    $ oc create -n <namespace> -f <destination-rule.yaml>
1.13.1.1.3. 최소 및 최대 프로토콜 버전 설정

사용자 환경에 서비스 메시의 암호화된 트래픽에 대한 특정 요구 사항이 있는 경우 ServiceMeshControlPlane 리소스에 spec.security.controlPlane.tls.minProtocolVersion 또는 spec.security.controlPlane.tls.maxProtocolVersion을 설정하여 허용되는 암호화 기능을 제어할 수 있습니다.

기본값은 TLS_AUTO이며 TLS 버전을 지정하지 않습니다.

표 1.5. 유효한 값

설명

TLS_AUTO

default

TLSv1_0

TLS 버전 1.0

TLSv1_1

TLS 버전 1.1

TLSv1_2

TLS 버전 1.2

TLSv1_3

TLS 버전 1.3

절차

  1. 웹 콘솔에 로그인합니다.
  2. Operators설치된 Operators를 클릭합니다.
  3. 제공된 API에서 Service Mesh Control Plane을 클릭합니다.
  4. ServiceMeshControlPlane 리소스의 이름(예: production)을 클릭합니다.
  5. YAML 탭을 클릭합니다.
  6. YAML 편집기에 다음 코드 조각을 삽입합니다. minProtocolVersion의 값을 TLS 버전 값으로 바꿉니다. 이 예에서 최소 TLS 버전은 TLSv1_2로 설정됩니다.

    ServiceMeshControlPlane 스니펫

    kind: ServiceMeshControlPlane
    spec:
      security:
        controlPlane:
          tls:
            minProtocolVersion: TLSv1_2

  7. 저장을 클릭합니다.
  8. 새로 고침을 클릭하여 변경 사항이 올바르게 업데이트되었는지 확인합니다.

1.13.1.2.

그림 1.5.

그림 1.6.

그림 1.7.

1.13.2. 역할 기반 액세스 제어(RBAC) 구성

RBAC(역할 기반 액세스 제어) 오브젝트에 따라 사용자 또는 서비스가 프로젝트 내에서 지정된 작업을 수행할 수 있는지가 결정됩니다. 메시의 워크로드에 대해 메시, 네임스페이스, 워크로드 전체 액세스 제어를 정의할 수 있습니다.

RBAC를 구성하려면 액세스를 구성하는 네임스페이스에 AuthorizationPolicy 리소스를 생성합니다.

예를 들어 RBAC를 사용하면 다음과 같은 정책을 생성할 수 있습니다.

  • 프로젝트 내 통신을 구성합니다.
  • 기본 네임스페이스의 모든 워크로드에 대한 전체 액세스를 허용하거나 거부합니다.
  • 수신 게이트웨이 액세스를 허용 또는 거부합니다.
  • 액세스 하려면 토큰이 필요합니다.

권한 부여 정책에는 선택기, 작업 및 규칙 목록이 포함됩니다.

  • selector 필드는 정책의 대상을 지정합니다.
  • action 필드는 요청을 허용하거나 거부할지 여부를 지정합니다.
  • rules 필드는 작업을 트리거할 시기를 지정합니다.

    • from 필드는 요청 원본에 대한 제약 조건을 지정합니다.
    • to 필드는 요청 대상 및 매개변수에 대한 제약 조건을 지정합니다.
    • when 필드는 규칙을 적용하기 위한 추가 조건을 지정합니다.

프로세스

  1. AuthorizationPolicy 리소스를 생성합니다. 다음 예제는 IP 주소가 수신 게이트웨이에 액세스하는 것을 거부하도록 ingress-policy AuthorizationPolicy를 업데이트하는 리소스를 보여줍니다.

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: ingress-policy
      namespace: istio-system
    spec:
      selector:
        matchLabels:
          app: istio-ingressgateway
      action: DENY
      rules:
      - from:
        - source:
          ipBlocks: ["1.2.3.4"]
  2. 리소스를 작성한 후 다음 명령어를 실행하여 네임스페이스에 리소스를 만듭니다. 네임스페이스는 AuthorizationPolicy 리소스의 metadata.namespace 필드와 일치해야 합니다.

    $ oc create -n istio-system -f <filename>

다음 단계

다른 일반적인 구성에 대해서는 다음 예제를 고려하십시오.

1.13.2.1. 프로젝트 내 통신 구성

1.13.2.1.1. 네임스페이스 외부 서비스에 대한 액세스 제한

다음 AuthorizationPolicy 리소스 예제를 사용하여 bookinfo 네임스페이스에 없는 모든 소스의 요청을 거부할 수 있습니다.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin-deny
 namespace: bookinfo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: DENY
 rules:
 - from:
   - source:
       notNamespaces: ["bookinfo"]
1.13.2.1.2. 권한 부여 모두 허용 및 권한 부여 모두 거부(기본) 정책 만들기

다음 예제에서는 bookinfo 네임스페이스의 모든 워크로드에 액세스할 수 있는 권한 부여 모두 허용 정책을 보여줍니다.

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

다음 예제에서는 bookinfo 네임스페이스의 모든 워크로드에 대한 액세스를 거부하는 정책을 보여줍니다.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
  namespace: bookinfo
spec:
  {}

1.13.2.2. 수신 게이트웨이에 대한 액세스 허용 또는 거부

IP 주소를 기반으로 허용 또는 거부 목록을 추가하도록 권한 부여 정책을 설정할 수 있습니다.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: ingress-policy
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: ALLOW
  rules:
  - from:
    - source:
       ipBlocks: ["1.2.3.4", "5.6.7.0/24"]

1.13.2.3. JSON 웹 토큰으로 액세스 제한

JSON 웹 토큰(JWT)으로 메시에 액세스하는 항목을 제한할 수 있습니다. 인증 후 사용자 또는 서비스는 해당 토큰과 연결된 경로, 서비스에 액세스할 수 있습니다.

워크로드에서 지원하는 인증 방법을 정의하는 RequestAuthentication 리소스를 생성합니다. 다음 예제에서는 http://localhost:8080/auth/realms/master에서 발행한 JWT를 수락합니다.

apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
  name: "jwt-example"
  namespace: bookinfo
spec:
  selector:
    matchLabels:
      app: httpbin
  jwtRules:
  - issuer: "http://localhost:8080/auth/realms/master"
    jwksUri: "http://keycloak.default.svc:8080/auth/realms/master/protocol/openid-connect/certs"

그런 다음, 동일한 네임스페이스에 AuthorizationPolicy 리소스를 생성하여, 사용자가 생성한 RequestAuthentication 리소스와 함께 작업할 수 있습니다. 다음 예제에서는 httpbin 워크로드에 요청을 보낼 때 Authorization 헤더에 JWT가 있어야 합니다.

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "frontend-ingress"
  namespace: bookinfo
spec:
  selector:
    matchLabels:
      app: httpbin
  action: DENY
  rules:
  - from:
    - source:
        notRequestPrincipals: ["*"]

1.13.3. 암호화 제품군 및 ECDH 곡선 구성

암호화 제품군 및 ECDH(Elliptic-curve Diffie–Hellman) 곡선은 서비스 메시를 보호하는 데 도움이 될 수 있습니다. 이러한 속성 중 하나가 비어 있으면 기본값이 사용됩니다.

서비스 메시에서 TLS 1.2 또는 이전 버전을 사용하는 경우 cipherSuites 설정이 적용됩니다. TLS 1.3을 사용할 때는 효과가 없습니다.

우선순위에 따라 암호화 제품군을 쉼표로 구분된 목록으로 설정합니다. 예를 들어 ecdhCurves: CurveP256, CurveP384CurveP256CurveP384보다 높은 우선순위로 설정합니다.

참고

암호화 제품군을 구성할 때 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 또는 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256을 포함해야 합니다. HTTP/2 지원에는 이러한 암호화 제품군 중 하나 이상이 필요합니다.

지원되는 암호화 제품군은 다음과 같습니다.

  • TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
  • TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_AES_128_GCM_SHA256
  • TLS_RSA_WITH_AES_256_GCM_SHA384
  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_128_CBC_SHA
  • TLS_RSA_WITH_AES_256_CBC_SHA
  • TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
  • TLS_RSA_WITH_3DES_EDE_CBC_SHA

지원되는 ECDH 곡선은 다음과 같습니다.

  • CurveP256
  • CurveP384
  • CurveP521
  • X25519

1.13.4. 외부 인증 기관 키 및 인증서 추가

기본적으로 Red Hat OpenShift Service Mesh는 자체 서명된 루트 인증서와 키를 생성하고 이를 사용하여 워크로드 인증서에 서명합니다. 사용자 정의 인증서 및 키를 사용하여 사용자 정의 루트 인증서로 워크로드 인증서에 서명할 수도 있습니다. 이 작업은 인증서와 키를 서비스 메시에 연결하는 예제를 보여줍니다.

사전 요구 사항

  • 인증서를 구성하려면 상호 TLS가 활성화된 Red Hat OpenShift Service Mesh를 설치합니다.
  • 프로덕션의 경우 인증 기관의 자체 인증서를 사용합니다.
  • 이러한 지침으로 결과를 확인하려면 Bookinfo 샘플 애플리케이션을 배포합니다.

1.13.4.1. 기존 인증서 및 키 추가

기존 서명(CA) 인증서 및 키를 사용하려면 CA 인증서, 키, 루트 인증서가 포함된 신뢰 파일 체인을 생성해야 합니다. 해당 인증서 각각에 대해 다음과 같은 정확한 파일 이름을 사용해야 합니다. CA 인증서를 ca-cert.pem, 키는 ca-key.pem이라고 합니다. ca-cert.pem을 서명하는 루트 인증서는 root-cert.pem이라고 합니다. 워크로드에서 중개 인증서를 사용하는 경우 cert-chain.pem 파일에 인증서를 지정해야 합니다.

  1. $ oc create secret generic cacerts -n istio-system --from-file=<path>/ca-cert.pem \
        --from-file=<path>/ca-key.pem --from-file=<path>/root-cert.pem \
        --from-file=<path>/cert-chain.pem
  2. 기본 rootCADir/etc/cacerts입니다. 키와 인증서가 기본 위치에 마운트된 경우 privateKey를 설정할 필요가 없습니다. 서비스 메시는 secret-mount 파일에서 인증서와 키를 읽습니다.

    apiVersion: maistra.io/v2
    kind: ServiceMeshControlPlane
    spec:
      security:
        dataPlane:
          mtls: true
        certificateAuthority:
          type: Istiod
          istiod:
            type: PrivateKey
            privateKey:
              rootCADir: /etc/cacerts
  3. $ oc -n istio-system delete pods -l 'app in (istiod,istio-ingressgateway, istio-egressgateway)'

  4. $ oc -n bookinfo delete pods --all

    출력은 다음과 유사합니다.

    pod "details-v1-6cd699df8c-j54nh" deleted
    pod "productpage-v1-5ddcb4b84f-mtmf2" deleted
    pod "ratings-v1-bdbcc68bc-kmng4" deleted
    pod "reviews-v1-754ddd7b6f-lqhsv" deleted
    pod "reviews-v2-675679877f-q67r2" deleted
    pod "reviews-v3-79d7549c7-c2gjs" deleted
  5. $ oc get pods -n bookinfo

1.13.4.2. 인증서 확인

  1. $ sleep 60
    $ oc -n bookinfo exec "$(oc -n bookinfo get pod -l app=productpage -o jsonpath={.items..metadata.name})" -c istio-proxy -- openssl s_client -showcerts -connect details:9080 > bookinfo-proxy-cert.txt
    $ sed -n '/-----BEGIN CERTIFICATE-----/{:start /-----END CERTIFICATE-----/!{N;b start};/.*/p}' bookinfo-proxy-cert.txt > certs.pem
    $ awk 'BEGIN {counter=0;} /BEGIN CERT/{counter++} { print > "proxy-cert-" counter ".pem"}' < certs.pem

  2. <path>를 인증서 경로로 교체합니다.

    $ openssl x509 -in <path>/root-cert.pem -text -noout > /tmp/root-cert.crt.txt

    $ openssl x509 -in ./proxy-cert-3.pem -text -noout > /tmp/pod-root-cert.crt.txt

    $ diff -s /tmp/root-cert.crt.txt /tmp/pod-root-cert.crt.txt

  3. <path>를 인증서 경로로 교체합니다.

    $ openssl x509 -in <path>/ca-cert.pem -text -noout > /tmp/ca-cert.crt.txt

    $ openssl x509 -in ./proxy-cert-2.pem -text -noout > /tmp/pod-cert-chain-ca.crt.txt

    $ diff -s /tmp/ca-cert.crt.txt /tmp/pod-cert-chain-ca.crt.txt

  4. 루트 인증서에서 워크로드 인증서로의 인증서 체인을 확인합니다. <path>를 인증서 경로로 교체합니다.

    $ openssl verify -CAfile <(cat <path>/ca-cert.pem <path>/root-cert.pem) ./proxy-cert-1.pem

1.13.4.3. 인증서 제거

추가한 인증서를 제거하려면 다음 단계를 따르십시오.

  1. 시크릿 cacerts를 제거합니다.

    $ oc delete secret cacerts -n istio-system
  2. ServiceMeshControlPlane 리소스에서 자체 서명된 루트 인증서로 서비스 메시를 재배포합니다.

    apiVersion: maistra.io/v2
    kind: ServiceMeshControlPlane
    spec:
      security:
        dataPlane:
          mtls: true