JWT와 함께 Istio를 사용하는 보안 마이크로서비스

Istiosecurity pillar는 강력한 ID(v1.14 이후 SPIRE와 선택적 통합 포함), 인증 및 승인(OPA과 선택적 통합 포함)으로 워크로드를 보호하는 포괄적인 솔루션을 제공합니다. Istio 사이드카(서비스 프록시) 및 ingressgateway(에지 프록시)는 전체 메시에 대한 PEP 역할을 합니다.

NIST SP 800-207에 따르면 어떤 리소스도 본질적으로 신뢰할 수 없으며 1) 모든 자산(서비스)은 요청이 승인되기 전에 PEP를 통해 보안 상태를 평가해야 합니다 ... 2) 평가는 세션이 지속되는 한 계속되어야 합니다. 지속됩니다. Istio는 일반적으로 L7에서 작동합니다. 그리고 심층 방어 전략을 구현하기 위해 NetworkPolicy을 통해 L3/4 적용으로 이를 보완해야 합니다. additional security considerations을 확인하십시오. 이에 대해서는 언급하지 않겠습니다. 대신 Istio with JWT를 사용하여 워크로드를 보호하는 방법을 안내해 드리겠습니다.

auth0을 통해 무료 JWT 토큰을 얻을 수 있습니다. demo 에 사용할 것입니다.

당연히 PeerAuthentication을 사용하여 mTLS를 적용해야 합니다. 기본적으로 IstioenableAutoMtlstrue로 설정되어 있지만 PERMISSIVE 모드였습니다.

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


요청이 JWT 토큰 없이 또는 RequestAuthenticationAuthorizationPolicy 조합이 있는 잘못된 JWT 토큰 없이 에지(istio-ingressgateway)에서 요청이 거부되었는지 확인해야 합니다.
RequesetAuthentication CRD는 JWT 토큰이 지정된 jwtRules를 준수하는지 확인합니다.

apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
  name: jwt-authn-gw
  namespace: istio-gateway
spec:
  selector:
    matchLabels:
      istio: ingressgateway
  jwtRules:
  - issuer: "https://dev-wl5b26zy.us.auth0.com/"
    jwksUri: "https://dev-wl5b26zy.us.auth0.com/.well-known/jwks.json"
    audiences:
    - "https://httpbin/api"
    forwardOriginalToken: true


JWT Token은 일반적으로 비대칭 서명 알고리즘으로 RS256(RSA Signature with SHA-256)을 사용합니다. Istio는 jwksUri를 통해 디지털 서명을 확인하여 토큰이 실제로 유효하고 변조 방지되는지 확인합니다. 요청이 들어오면 다양한 HTTP filters 을 거치는데, 그 중 하나가 envoy.filters.http.jwt_authn 입니다. 효율성을 높이기 위해 JWKS는 localJwks에 "캐시"되어 jwksUri 끝점에 대한 아웃바운드 호출을 매번 수행하는 대신 성능을 향상시킵니다.

...
{
    "name": "envoy.filters.http.jwt_authn",
    "typedConfig": {
        "@type": "type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication",
        "providers": {
            "origins-0": {
                "issuer": "https://dev-wl5b26zy.us.auth0.com/",
                "audiences": [
                    "https://httpbin/api"
                ],
                "localJwks": {
                    "inlineString": "..."
                },
                "forward": true,
                "payloadInMetadata": "https://dev-wl5b26zy.us.auth0.com/"
            }
        },
...
}
...

istio_authn 필터는 jwt_authn 필터 바로 뒤에 있습니다. 그리고 발급자도 확인하려고 시도합니다.

{
    "name": "istio_authn",
    "typedConfig": {
        "@type": "type.googleapis.com/istio.envoy.config.filter.http.authn.v2alpha1.FilterConfig",
        "policy": {
            "origins": [
                {
                    "jwt": {
                        "issuer": "https://dev-wl5b26zy.us.auth0.com/"
                    }
                }
            ],
            "originIsOptional": true,
            "principalBinding": "USE_ORIGIN"
        },
        "skipValidateTrustDomain": true
    }
}

RequesetAuthentication만으로는 a request without any authentication credentials will be accepted but will not have any authenticated identity 이후로 충분하지 않습니다. 그렇기 때문에 시행할 장소에 AuthorizationPolicy가 있어야 합니다.

먼저 RequestPrincipal 가 없으면 istio-ingressgateway에서 요청이 거부된다고 규정합니다.

apiVersion: "security.istio.io/v1beta1"
kind: AuthorizationPolicy
metadata:
  name: deny-jwt-gw
  namespace: istio-gateway
spec:
  selector:
    matchLabels:
      istio: ingressgateway
  action: DENY
  rules:
  - from:
    - source:
        notRequestPrincipals: ["*"]


둘째, 서비스 수준에서 워크로드가 기대하는 클레임을 충족해야 합니다. 작동하게 하려면 JWT 토큰이 istio-ingressgateway에서 워크로드로 전달되도록 허용하는 것이 중요합니다forwardOriginalToken: true.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-jwt-httpbin
  namespace: default
spec:
  selector:
    matchLabels:
      app: httpbin
  action: ALLOW
  rules:
  - from:
    - source:
        requestPrincipals: ["https://dev-wl5b26zy.us.auth0.com//8qPXVf5npNa4yXmeyHhnGh5GDgrDK3B5@clients"]
    when:
    - key: request.auth.claims[scope]
      values: ["read:messages"]
    - key: request.auth.claims[aud]
      values: ["https://httpbin/api"]


이러한 시행은 envoy.filters.http.rbac라는 워크로드의 사이드카 EnvoyProxy HTTP 필터로 "인코딩"되었습니다. 모든 위반은 403 Forbidden 오류와 함께 RBAC: access denied를 유발합니다.

{
    "name": "envoy.filters.http.rbac",
    "typedConfig": {
        "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC",
        "rules": {
            "policies": {
                "ns[default]-policy[require-jwt-httpbin]-rule[0]": {
                    "permissions": [
                        {
                            "andRules": {
                                "rules": [
                                    {
                                        "any": true
                                    }
                                ]
                            }
                        }
                    ],
                    "principals": [
                        {
                            "andIds": {
                                "ids": [
                                    {
                                        "orIds": {
                                            "ids": [
                                                {
                                                    "metadata": {
                                                        "filter": "istio_authn",
                                                        "path": [
                                                            {
                                                                "key": "request.auth.principal"
                                                            }
                                                        ],
                                                        "value": {
                                                            "stringMatch": {
                                                                "exact": "https://dev-wl5b26zy.us.auth0.com//8qPXVf5npNa4yXmeyHhnGh5GDgrDK3B5@clients"
                                                            }
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    },
...
        },
        "shadowRulesStatPrefix": "istio_dry_run_allow_"
    }
}


읽어주셔서 감사하고 저와 함께 배워보세요. 직접 실행하려면 source code 및 지침이 있습니다.

짜잔!

좋은 웹페이지 즐겨찾기