Защита микросервисов с помощью Istio w/ JWT

Istio security pillar предоставляет комплексное решение для защиты рабочих нагрузок с помощью надежной идентификации (с дополнительной интеграцией с SPIRE с версии 1.14), аутентификации и авторизации (с дополнительной интеграцией с OPA). Istio sidecar (сервисный прокси) и ingressgateway (пограничный прокси) служат в качестве PEP для всего mesh.

Согласно NIST SP 800-207, ни один ресурс не является доверенным по своей сути, 1) каждый актив (сервис) ДОЛЖЕН иметь оценку своей безопасности через PEP перед тем, как запрос будет удовлетворен … 2) и оценка должна быть непрерывной в течение всего времени, пока длится сессия. Istio обычно работает на уровне L7. И для реализации стратегии Defense-in-Depth нам также необходимо дополнить ее принудительным применением L3/4 через NetworkPolicy. Пожалуйста, ознакомьтесь с дополнительными соображениями безопасности, а мы не будем об этом говорить. Вместо этого позвольте мне рассказать вам о том, как защитить рабочую нагрузку с помощью Istio с JWT.

Вы можете получить бесплатный JWT-токен через auth0. Мы будем использовать его для демонстрации.

Очевидно, что нам нужно обеспечить mTLS с помощью PeerAuthentication. По умолчанию для Istio enableAutoMtls установлено значение true, но он был в режиме PERMISSIVE.

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: istio-system
spec:
  mtls:
    mode: STRICT
Вход в полноэкранный режим Выход из полноэкранного режима

Нам нужно убедиться, что запрос ДОЛЖЕН быть отклонен на границе (istio-ingressgateway) либо без JWT-токена, либо с недействительным JWT-токеном с помощью комбинации RequestAuthentication и AuthorizationPolicy.

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 обычно использует RS256 (RSA Signature with SHA-256) в качестве алгоритма асимметричной подписи. Istio убедится, что токен действительно действителен и защищен от взлома, проверив цифровую подпись через jwksUri. Когда приходит запрос, он проходит через различные HTTP фильтры, и один из них — 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 будет недостаточно, поскольку запрос без каких-либо учетных данных аутентификации будет принят, но не будет иметь аутентифицированной личности. Вот почему крайне важно иметь AuthorizationPolicy для обеспечения соблюдения.

Во-первых, она предусматривает, что запрос будет отклонен на istio-ingressgateway, если у него нет RequestPrincipal.

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: ["*"]
Вход в полноэкранный режим Выход из полноэкранного режима

Во-вторых, на уровне сервиса он должен удовлетворять требованиям, которые ожидает рабочая нагрузка. Для того чтобы это работало, важно иметь forwardOriginalToken: true, чтобы разрешить пересылку JWT-токена от istio-ingressgateway к рабочей нагрузке.

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"]
Вход в полноэкранный режим Выход из полноэкранного режима

Эти правила были «закодированы» в боковом EnvoyProxy HTTP Filter рабочей нагрузки под названием envoy.filters.http.rbac. Любое нарушение приведет к 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_"
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Спасибо, что читаете и учитесь вместе со мной. Если вы хотите запустить его самостоятельно, вот исходный код и инструкции.

Вуаля!

Оцените статью
devanswers.ru
Добавить комментарий