<p>I have applied kiali in Istio 1.10.2 by using <a href="https://raw.githubusercontent.com/istio/istio/1.10.2/samples/addons/kiali.yaml" rel="nofollow noreferrer">this</a>. Now I am trying to secure it by filtering source ip address. I tried using authorization policy but it didn't work. It keeps allowing everyone when <a href="https://istio.io/latest/docs/reference/config/security/authorization-policy/" rel="nofollow noreferrer">it should deny any request that is not in the ALLOW policy</a></p>
<p>AuthorizationPolicy:</p>
<pre><code>apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: kiali-ingress-policy-allow
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: kiali
  action: ALLOW
  rules:
  - from:
    - source:
        remoteIpBlocks: [&quot;10.43.212.247/32&quot;,&quot;10.43.212.242/32&quot;]
</code></pre>
<p>VirtualService:</p>
<pre><code>apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: kiali
  namespace: istio-system
spec:
  hosts:
  - &quot;kiali.myinternaldomain.local&quot;
  gateways:
  - istio-system/my-internal-gateway
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: kiali
        port:
          number: 20001
</code></pre>
<p>Installed ISTIO using default profile and these extra parameters:</p>
<pre><code>apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    accessLogFile: /dev/stdout
  components:
    ingressGateways:
      - name: istio-ingressgateway
        enabled: true
        k8s:
          overlays:
          - apiVersion: apps/v1
            kind: Deployment
            name: istio-ingressgateway
            patches:
            - path: kind
              value: DaemonSet
            - path: spec.strategy
            - path: spec.updateStrategy
              value:
                rollingUpdate:
                  maxUnavailable: 50%
                type: RollingUpdate
    egressGateways:
      - name: istio-egressgateway
        enabled: true
        k8s:
          hpaSpec:
            minReplicas: 2
    pilot:
      k8s:
        hpaSpec:
          minReplicas: 2
  values:
    gateways:
      istio-ingressgateway:
        autoscaleEnabled: false
        env:
          ISTIO_META_HTTP10: '1'
    pilot:
      env:
        PILOT_HTTP10: '1'
</code></pre>

<p>I manage to setup working <code>ALLOW</code> policy in the Istio 1.10.2 on <a href="https://cloud.google.com/compute" rel="nofollow noreferrer">GCP VMs</a>, the cluster is setup using kubeadm with Calico CNI plugin. I used this documentation - <a href="https://istio.io/latest/docs/tasks/security/authorization/authz-ingress/" rel="nofollow noreferrer">Ingress Gateway</a>.</p>
<p>Note: I changed <code>istio-ingressgateway</code> service type to <code>NodePort</code> service instead of <code>LoadBalancer</code>, but this does not matter in this case.</p>
<hr />
<p>My network design is following:</p>
<ul>
<li>First VM - Kubernetes node - 10.xxx.0.2 address</li>
<li>Second VM - 10.xxx.0.3 address</li>
<li>Third VM - 10.xxx.0.4 address - this address will be in the ALLOW policy</li>
</ul>
<p>I deployed the following NGINX service and deployment...</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deply
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
        version: v1
    spec:
      containers:
      - image: nginx
        imagePullPolicy: IfNotPresent
        name: nginx
        ports:
        - containerPort: 80
</code></pre>
<p>... and following gateway and virtual service definitions:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - &quot;*&quot;
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginx-vs
spec:
  hosts:
  - &quot;my-test.com&quot;
  gateways:
  - gateway
  http:
  - route:
    - destination:
        host: nginx-svc 
        port:
          number: 80
</code></pre>
<p>Take a look at the <code>nginx-svc</code> service name in virtual service definition (you should use the one that you want to configure).</p>
<p>From every VM in the network I can run following command:</p>
<pre><code>user@vm-istio:~$ curl 10.xxx.0.2:31756 -H &quot;Host: my-test.com&quot;
&lt;!DOCTYPE html&gt;
...
&lt;title&gt;Welcome to nginx!&lt;/title&gt;
</code></pre>
<p>So it's working properly.</p>
<p>I <a href="https://istio.io/latest/docs/tasks/security/authorization/authz-ingress/#before-you-begin" rel="nofollow noreferrer">enabled RBAC debugging for the ingress gateway pod</a>...</p>
<pre><code>kubectl get pods -n istio-system -o name -l istio=ingressgateway | sed 's|pod/||' | while read -r pod; do istioctl proxy-config log &quot;$pod&quot; -n istio-system --level rbac:debug; done
</code></pre>
<p>...and I set <code>externalTrafficPolicy</code> to <code>Local</code> in service <code>istio-ingressgateway</code> to <a href="https://istio.io/latest/docs/tasks/security/authorization/authz-ingress/#source-ip-address-of-the-original-client" rel="nofollow noreferrer">preserve an IP address from the original client</a>:</p>
<pre><code>kubectl patch svc istio-ingressgateway -n istio-system -p '{&quot;spec&quot;:{&quot;externalTrafficPolicy&quot;:&quot;Local&quot;}}
</code></pre>
<p>In the logs of the istio ingress gateway controller I can the that requests are coming and they are being proceed:</p>
<pre><code>kubectl logs istio-ingressgateway-5d57955454-9mz4b -n istio-system -f
...
[2021-11-24T13:39:47.220Z] &quot;GET / HTTP/1.1&quot; 200 - via_upstream - &quot;-&quot; 0 615 1 0 &quot;10.xxx.0.3&quot; &quot;curl/7.64.0&quot; &quot;69953f69-8a46-9e2a-a5a7-36861bae4a77&quot; &quot;my-test.com&quot; &quot;192.168.98.74:80&quot; outbound|80||nginx-svc.default.svc.cluster.local 192.168.98.72:60168 192.168.98.72:8080 10.xxx.0.3:55160 - -
[2021-11-24T13:39:48.980Z] &quot;GET / HTTP/1.1&quot; 200 - via_upstream - &quot;-&quot; 0 615 1 0 &quot;10.xxx.0.4&quot; &quot;curl/7.64.0&quot; &quot;89284e11-42f9-9e84-b256-d3ea37311e92&quot; &quot;my-test.com&quot; &quot;192.168.98.74:80&quot; outbound|80||nginx-svc.default.svc.cluster.local 192.168.98.72:60192 192.168.98.72:8080 10.xxx.0.4:35800 - -
</code></pre>
<p>Now, I will apply IP-based allow list to allow only second VM address to host <code>my-test.com</code>:</p>
<pre class="lang-yaml prettyprint-override"><code>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: [&quot;10.xxx.0.4&quot;]
    to:
    - operation:
        hosts:
        - &quot;my-test.com&quot; 
</code></pre>
<p>On the VM with address 10.xxx.0.4 curl is working as before, but on the VM with address 10.xxx.0.3 we can notice following:</p>
<pre><code>user@vm-istio:~$ curl 10.xxx.0.2:31756 -H &quot;Host: my-test.com&quot;
RBAC: access denied
</code></pre>
<p>So it's working as expected.</p>
<p>In the logs of the istio ingress gateway controller we can notice that request is denied (look for the logs related to the RBAC):</p>
<pre><code>kubectl logs istio-ingressgateway-5d57955454-9mz4b -n istio-system -f
2021-11-24T14:05:11.382613Z     debug   envoy rbac      checking request: requestedServerName: , sourceIP: 10.xxx.0.3:55194, directRemoteIP: 10.xxx.0.3:55194, remoteIP: 10.xxx.0.3:55194,localAddress: 192.168.98.72:8080, ssl: none, headers: ':authority', 'my-test.com'
':path', '/'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/7.64.0'
'accept', '*/*'
'x-forwarded-for', '10.xxx.0.3'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', '63c0f55c-5545-92a0-80fc-aa2a5a63bf04'
'x-envoy-decorator-operation', 'nginx-svc.default.svc.cluster.local:80/*'
'x-envoy-peer-metadata', '...'
'x-envoy-peer-metadata-id', 'router~192.168.98.72~istio-ingressgateway-5d57955454-9mz4b.istio-system~istio-system.svc.cluster.local'
, dynamicMetadata: 
2021-11-24T14:05:11.382662Z     debug   envoy rbac      enforced denied, matched policy none
[2021-11-24T14:05:11.382Z] &quot;GET / HTTP/1.1&quot; 403 - rbac_access_denied_matched_policy[none] - &quot;-&quot; 0 19 0 - &quot;10.xxx.0.3&quot; &quot;curl/7.64.0&quot; &quot;63c0f55c-5545-92a0-80fc-aa2a5a63bf04&quot; &quot;my-test.com&quot; &quot;-&quot; outbound|80||nginx-svc.default.svc.cluster.local - 192.168.98.72:8080 10.xxx.0.3:55194 - -
</code></pre>
<p>Especially this part:</p>
<pre><code>[2021-11-24T14:05:11.382Z] &quot;GET / HTTP/1.1&quot; 403 - rbac_access_denied_matched_policy[none]
</code></pre>
<p>It clearly shows that our policy is working.</p>
<p>Example of the log that allowed our request:</p>
<pre><code>2021-11-25T10:58:34.717495Z     debug   envoy rbac      enforced allowed, matched policy ns[istio-system]-policy[ingress-policy]-rule[0]
[2021-11-25T10:58:34.717Z] &quot;GET / HTTP/1.1&quot; 200 - via_upstream - &quot;-&quot; 0 615 25 23 &quot;10.xxx.0.4&quot; &quot;curl/7.64.0&quot; &quot;889e3326-093c-94b1-b856-777c06cbe2b7&quot; &quot;my-test.com&quot; &quot;192.168.98.75:80&quot; outbound|80||nginx-svc.default.svc.cluster.local 192.168.98.72:46190 192.168.98.72:8080 10.xxx.0.4:37148 - -
</code></pre>
<p>What's important:</p>
<ul>
<li>make sure that in logs of the pod <code>istio-ingressgateway-{..}</code> you can notice the source IP address of the other VM so the policy can allow / block</li>
<li>my advice is to setup AuthorizationPolicy <strong>for external traffic</strong> at the edge of service mesh - which is istio ingress gateway, that’s why my AuthorizationPolicy is using “selector” matching label <code>app: ingress-istio-ingressgateway</code> (not the kiali)</li>
<li><a href="https://istio.io/latest/docs/tasks/security/authorization/authz-ingress/#ip-based-allow-list-and-deny-list" rel="nofollow noreferrer">use a proper type of IPs - <code>ipBlocks</code> vs <code>remoteIpBlocks</code></a>. Base on your setup, it should be <code>ipBlocks</code>:</li>
</ul>
<blockquote>
<p><strong>When to use  <code>ipBlocks</code>  vs.  <code>remoteIpBlocks</code>:</strong> If you are using the X-Forwarded-For HTTP header or the Proxy Protocol to determine the original client IP address, then you should use <code>remoteIpBlocks</code> in your <code>AuthorizationPolicy</code>. If you are using <code>externalTrafficPolicy: Local</code>, then you should use <code>ipBlocks</code> in your <code>AuthorizationPolicy</code>.</p>
</blockquote>
