Istio授权策略不适用于子网关 [英] Istio authorization policy not applying on child gateway

查看:95
本文介绍了Istio授权策略不适用于子网关的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要实现的目标:阻止所有流量到服务,其中包含在与服务相同的名称空间中处理该流量的代码.

What I am trying to achieve: block all traffic to a service, containing the code to handle this within the same namespace as the service.

原因:这是锁定"广告代码的第一步针对特定IP/CIDR的特定服务

Why: this is the first step in "locking down" a specific service to specific IPs/CIDRs

我有一个名为istio-ingressgateway的主要入口GW,可用于服务.

I have a primary ingress GW called istio-ingressgateway which works for services.

$ 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,即支持TLS的K8s入口GW(我想将其包括在内,尽可能明确)

I also have another "primary" GW, the K8s ingress GW to support TLS (thought I'd include this, to be as explicit as possible)

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>

我希望能够在名称空间x中创建另一个GW,并将授权策略附加到该GW. 如果我在istio-system命名空间中创建授权策略,那么它会随RBAC: access denied一起返回,这很棒-但这适用于使用主GW的所有服务.

I want to be able to create another GW, in the namespace x and have an authorization policy attached to that GW. If I create the authorization policy in the istio-system namespace, then it comes back with RBAC: access denied which is great - but that is for all services using the primary 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"]

我当前拥有的东西不起作用.任何指针将不胜感激.应用kubectl apply -f files.yaml -n x

What I currently have does not work. Any pointers would be highly appreciated. The following are all created under the x namespace when applying the 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的所有流量,因为它符合0.0.0.0/0

The above should be blocking all traffic to the GW, as it matches on the CIDR range of 0.0.0.0/0

我完全误解了GW/AuthorizationPolicies的概念,或者我错过了什么?

I am entirely misunderstanding the concept of GWs/AuthorizationPolicies or have I missed something?

修改 我最终创建了另一个具有IP限制块的GW,因为AWS上的传统负载均衡器不支持IP转发.

Edit I ended up creating another GW which had the IP restriction block on that, as classic load balancers on AWS do not support IP forwarding.

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"}}'

然后我在要锁定的工作负载中使用了该网关.

I then used that gateway in my workload that I wanted to lock down.

推荐答案

据我所知,您应该使用

As far as I know you should rather use AuthorizationPolicy in 3 ways

  • 在入口网关上
  • 在命名空间上
  • 关于特定服务

我已经尝试过像您一样在具有注释的特定网关上使用它,但是我无法使其适用于我.

I have tried to make it work on a specific gateway with annotations like you did, but I couldn't make it work for me.

例如

以下授权策略拒绝对名称空间x中的工作负载的所有请求.

the following authorization policy denies all requests to workloads in namespace x.

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

以下授权策略拒绝入口网关上的所有请求.

the following authorization policy denies all requests on ingress gateway.

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

以下授权策略拒绝 httpbin上的所有请求在x名称空间中.

the following authorization policy denies all requests on httpbin in x namespace.

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


比方说,您拒绝x名称空间上的所有请求,并且仅允许获取针对httpbin服务的请求.


Let's say you deny all requests on x namespace and allow only get requests for httpbin service.

然后,您将使用此AuthorizationPolicy拒绝所有请求

Then you would use this AuthorizationPolicy to deny all requests

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

此AuthorizationPolicy仅允许获取请求.

And this AuthorizationPolicy to allow only get requests.

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在此处提到的

As mentioned here by @incfly

我猜想它在非入口Pod中停止工作的原因是因为sourceIP属性将不再是真正的客户端IP.

I guess the reason why it’s stop working when in non ingress pod is because the sourceIP attribute will not be the real client IP then.

根据 https://github.com/istio/istio/issues/22341 7(尚未完成)旨在在不将k8s externalTrafficPolicy设置为local的情况下提供更好的支持,并且还支持CIDR范围.

According to https://github.com/istio/istio/issues/22341 7, (not done yet) this aims at providing better support without setting k8s externalTrafficPolicy to local, and supports CIDR range as well.


我从 istio文档中尝试了此示例使它起作用,但是即使我更改了externalTrafficPolicy,它也对我不起作用.然后,使用 envoyfilter 的解决方法来自istio讨论线程


I have tried this example from istio documentation to make it work, but it wasn't working for me, even if I changed externalTrafficPolicy. Then a workaround with envoyfilter came from above istio discuss thread.

@ hleal18提供的答案

Answer provided by @hleal18 here.

使用EnvoyFilters(尤其是在httbin上应用了remote_ip条件)成功地完成了示例.

Got and example working successfully using EnvoyFilters, specifically with remote_ip condition applied on 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


我已经在我的测试集群上尝试了以上使节过滤器,并且据我所知它正在工作.


I have tried above envoy filter on my test cluster and as far as I can see it's working.

看看我执行的以下步骤.

Take a look at below steps I made.

1.我已通过以下方式更改了externalTrafficPolicy

1.I have changed the externalTrafficPolicy with

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

2.我创建了启用istio-injection的命名空间x并在此处部署了httpbin.

2.I have created namespace x with istio-injection enabled and deployed httpbin here.

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

3.I have created 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 ,我曾经使用过一些命令来获取它.

address_prefix is the CLIENT_IP, there are commands I have used to get it.

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和浏览器对其进行了测试.

4.I have test it with curl and my browser.

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

如果您还有其他疑问,请告诉我.

Let me know if you have any more questions, I might be able to help.

这篇关于Istio授权策略不适用于子网关的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆