Политика авторизации Istio не применяется на дочернем шлюзе

Чего я пытаюсь достичь: заблокировать весь трафик службы, содержащий код для его обработки в том же пространстве имен, что и служба.

Почему: это первый шаг к привязке определенной службы к определенным IP / CIDR.

У меня есть первичный входящий GW под названием istio-ingressgateway, который работает для служб.

$ kubectl describe gw istio-ingressgateway -n istio-system
Name:         istio-ingressgateway
Namespace:    istio-system
Labels:       operator.istio.io/component=IngressGateways
              operator.istio.io/managed=Reconcile
              operator.istio.io/version=1.5.5
              release=istio
Annotations:  API Version:  networking.istio.io/v1beta1
Kind:         Gateway
Metadata:
  Creation Timestamp:  2020-08-28T15:45:10Z
  Generation:          1
  Resource Version:    95438963
  Self Link:           /apis/networking.istio.io/v1beta1/namespaces/istio-system/gateways/istio-ingressgateway
  UID:                 ae5dd2d0-44a3-4c2b-a7ba-4b29c26fa0b9
Spec:
  Selector:
    App:    istio-ingressgateway
    Istio:  ingressgateway
  Servers:
    Hosts:
      *
    Port:
      Name:      http
      Number:    80
      Protocol:  HTTP
Events:          <none>

У меня также есть еще один основной GW, входящий GW K8s для поддержки TLS (думал, что включил бы это, чтобы быть как можно более явным)

k describe gw istio-autogenerated-k8s-ingress -n istio-system
Name:         istio-autogenerated-k8s-ingress
Namespace:    istio-system
Labels:       app=istio-ingressgateway
              istio=ingressgateway
              operator.istio.io/component=IngressGateways
              operator.istio.io/managed=Reconcile
              operator.istio.io/version=1.5.5
              release=istio
Annotations:  API Version:  networking.istio.io/v1beta1
Kind:         Gateway
Metadata:
  Creation Timestamp:  2020-08-28T15:45:56Z
  Generation:          2
  Resource Version:    95439499
  Self Link:           /apis/networking.istio.io/v1beta1/namespaces/istio-system/gateways/istio-autogenerated-k8s-ingress
  UID:                 edd46c17-9975-4089-95ff-a2414d40954a
Spec:
  Selector:
    Istio:  ingressgateway
  Servers:
    Hosts:
      *
    Port:
      Name:      http
      Number:    80
      Protocol:  HTTP
    Hosts:
      *
    Port:
      Name:      https-default
      Number:    443
      Protocol:  HTTPS
    Tls:
      Credential Name:     ingress-cert
      Mode:                SIMPLE
      Private Key:         sds
      Server Certificate:  sds
Events:                    <none>

Я хочу иметь возможность создать еще один GW в пространстве имен x и иметь политику авторизации, прикрепленную к этому GW. Если я создам политику авторизации в пространстве имен istio-system, она возвращается с RBAC: access denied, что отлично, но это касается всех служб, использующих основной GW.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: block-all
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: DENY
  rules:
    - from:
        - source:
            ipBlocks: ["0.0.0.0/0"]

То, что у меня сейчас есть, не работает. Будем очень признательны за любые указатели. Следующие элементы создаются в пространстве имен x при применении kubectl apply -f files.yaml -n x

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  annotations:
      app: x-ingress
  name: x-gw
  labels:
    app: x-ingress
spec:
  selector:
    istio: ingressgateway
  servers:
    - hosts:
        - x.y.com
      port:
        name: http
        number: 80
        protocol: HTTP
      tls:
        httpsRedirect: true
    - hosts:
        - x.y.com
      port:
        name: https
        number: 443
        protocol: HTTPS
      tls:
        mode: SIMPLE
        privateKey: sds
        serverCertificate: sds
        credentialName: ingress-cert
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: x
  labels:
    app: x
spec:
  hosts:
    - x.y.com
  gateways:
    - x-gw
  http:
    - route:
        - destination:
            host: x
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: x-ingress-policy
spec:
  selector:
    matchLabels:
      app: x-ingress
  action: DENY
  rules:
    - from:
        - source:
            ipBlocks: ["0.0.0.0/0"]
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: x
  labels:
    app: x
spec:
  hosts:
    - x.y.com
  gateways:
    - x-gw
  http:
    - route:
        - destination:
            host: x

Вышеупомянутое должно блокировать весь трафик к GW, так как он соответствует диапазону CIDR 0.0.0.0/0.

Я совершенно не понимаю концепцию GW / AuthorizationPolicies или я что-то пропустил?

Изменить. В итоге я создал еще один GW с блокировкой ограничения IP-адресов, поскольку классические балансировщики нагрузки на AWS не поддерживают переадресацию IP-адресов.

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  namespace: istio-system
  name: istiocontrolplane
spec:
  profile: demo
  components:
    ingressGateways:
      - name: istio-ingressgateway
        enabled: true
      - name: admin-ingressgateway
        enabled: true
        label:
          istio: admin-ingressgateway
        k8s:
          serviceAnnotations:
            service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all-admin
  namespace: istio-system
spec:
  selector:
    matchLabels:
      istio: admin-ingressgateway
  action: ALLOW
  rules:
    - from:
        - source:
            ipBlocks: ["176.252.114.59/32"]
kubectl patch svc istio-ingressgateway -n istio-system -p '{"spec":{"externalTrafficPolicy":"Local"}}'

Затем я использовал этот шлюз в своей рабочей нагрузке, которую хотел заблокировать.


person James Elliott    schedule 29.08.2020    source источник
comment
Я думаю, что это отличный вопрос, который нужно решить, однако я бы предложил создать простую диаграмму по текущим и желаемым сценариям, это поможет быстрее получить идею и, возможно, больше ответов;)   -  person Rafael Aguilar    schedule 31.08.2020


Ответы (1)


Насколько мне известно, вам лучше использовать AuthorizationPolicy в 3 способа

  • на входном шлюзе
  • в пространстве имен
  • по конкретной услуге

Я пытался заставить его работать на конкретном шлюзе с аннотациями, как вы, но не смог заставить его работать для меня.

e.g.

следующая политика авторизации отклоняет все запросы к рабочим нагрузкам в пространстве имен x.

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

следующая политика авторизации отклоняет все запросы на входном шлюзе.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway

следующая политика авторизации отклоняет все запросы на https://raw.githubusercontent.com/istio/istio/release-1.7/samples/httpbin/httpbin.yaml в пространстве имен x.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-service-x
  namespace: x
spec:
  selector:
    matchLabels:
      app: httpbin

Допустим, вы отклоняете все запросы в пространстве имен x и разрешаете получать запросы только для службы httpbin.

Затем вы должны использовать эту AuthorizationPolicy, чтобы отклонить все запросы

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

И эта AuthorizationPolicy позволяет только получать запросы.

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "x-viewer"
  namespace: x
spec:
  selector:
    matchLabels:
      app: httpbin
  rules:
  - to:
    - operation:
        methods: ["GET"]

И главная проблема - это ipBlocks. По этому поводу есть связанная проблема с github.

Как упоминалось здесь @incfly

Я предполагаю, что причина, по которой он перестает работать, когда он находится в не входящем модуле, заключается в том, что тогда атрибут sourceIP не будет реальным IP-адресом клиента.

Согласно https://github.com/istio/istio/issues/22341 7 , (еще не сделано) это нацелено на обеспечение лучшей поддержки без установки k8s externalTrafficPolicy на local, а также поддерживает диапазон CIDR.


Я пробовал этот пример из документации istio, чтобы сделать его работают, но у меня не получалось, даже если я поменял externalTrafficPolicy. Затем из вышеупомянутой темы обсуждения istio было найдено обходное решение с помощью envoyfilter .

Ответ предоставлен @ hleal18 здесь.

Получил и пример успешно работает с использованием EnvoyFilters, в частности, с условием remote_ip, примененным к httbin.

Предоставление манифеста для справки.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: httpbin
  namespace: foo
spec:
  workloadSelector:
    labels:
      app: httpbin
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: SIDECAR_INBOUND
        listener:
          filterChain:
            filter:
              name: "envoy.http_connection_manager"
              subFilter:
                name: "envoy.router"
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.filters.http.rbac 
          config:
            rules:
              action: ALLOW
              policies:
                "ip-premissions":
                  permissions:
                    - any: true
                  principals:
                    - remote_ip:
                        address_prefix: xxx.xxx.xx.xx
                        prefix_len: 32

Я пробовал вышеуказанный фильтр посланника на своем тестовом кластере, и, насколько я вижу, он работает.

Взгляните на шаги, которые я сделал ниже.

1. Я изменил externalTrafficPolicy с помощью

kubectl patch svc istio-ingressgateway -n istio-system -p '{"spec":{"externalTrafficPolicy":"Local"}}'

2. Я создал пространство имен x с включенной istio-инъекцией и развернул здесь httpbin.

kubectl create namespace x
kubectl label namespace x istio-injection=enabled
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.7/samples/httpbin/httpbin.yaml -n x
kubectl apply -f https://github.com/istio/istio/blob/master/samples/httpbin/httpbin-gateway.yaml -n x

3.Я создал envoyfilter

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: httpbin
  namespace: x
spec:
  workloadSelector:
    labels:
      app: httpbin
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: SIDECAR_INBOUND
        listener:
          filterChain:
            filter:
              name: "envoy.http_connection_manager"
              subFilter:
                name: "envoy.router"
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.filters.http.rbac
          config:
            rules:
              action: ALLOW
              policies:
                "ip-premissions":
                  permissions:
                    - any: true
                  principals:
                    - remote_ip:
                        address_prefix: xx.xx.xx.xx
                        prefix_len: 32

address_prefix - это CLIENT_IP, есть команды, которые я использовал для его получения.

export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
curl "$INGRESS_HOST":"$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n"
CLIENT_IP=$(curl "$INGRESS_HOST":"$INGRESS_PORT"/ip -s | grep "origin" | cut -d'"' -f 4) && echo "$CLIENT_IP"

4. Я протестировал его с помощью curl и моего браузера.

curl "$INGRESS_HOST":"$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n"
200

введите описание изображения здесь


Дайте мне знать, если у вас возникнут еще вопросы, я смогу помочь.

person Jakub    schedule 01.09.2020
comment
Спасибо, Якуб. Хотя это не сработало (я думаю, что HTTPS-вход куда-то вмешивается), это действительно помогло мне на пути к решению этой проблемы. Спасибо! - person James Elliott; 02.09.2020