Cannot use JWT policy with an ExternalName VirtualService target

Kubernetes: 1.13.5
Istio: 1.1.7

I have configured the following ExternalName service for httpbin.org in Kubernetes.

>kubectl apply -f - <<EOF
apiVersion: v1                                
kind: Service
metadata:
  name: httpbinext
  namespace: foo
spec:
  externalName: httpbin.org
  ports:
  - name: http-httpbinext
    port: 80                           
    protocol: TCP                                                                                              
    targetPort: 80
  sessionAffinity: None
  type: ExternalName
EOF

I have also configured the following VirtualService

>kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbinext
  namespace: foo
spec:
  hosts:
  - httpbinext.foo.svc.cluster.local
  gateways:
  - mesh                               
  - httpbinext-gateway                                                                                         
  http:                       
  - route:
    - destination:
        host: httpbinext
    corsPolicy:
      allowOrigin:
      - 'example.com'
      allowMethods:
      - POST
      - GET
      allowCredentials: false
      allowHeaders:
      - X-Foo-Bar
      - X-Bar-Foo
      maxAge: "24h"
EOF

as well as this Gateway configuration

>kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbinext-gateway
  namespace: foo        
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:                        
      number: 80                                                                                               
      name: http
      protocol: HTTP
    hosts:
    - "httpbinext.foo.svc.cluster.local"
EOF

With the above setup I have managed to access the external service (httpbin) through the Istio Gateway and my goal is to evaluate some Istio features. For example, a preflight CORS request which is working fine:

>curl --head -X OPTIONS $INGRESS_URL/headers -s -H 'Host: httpbinext.foo.svc.cluster.local' -H 'Access-Control-Request-Method: GET' -H 'Access-Control-Request-Headers: Content-Type, Accept' -H 'Origin:example.com'
HTTP/1.1 200 OK
access-control-allow-origin: example.com
access-control-allow-methods: POST,GET
access-control-allow-headers: X-Foo-Bar,X-Bar-Foo
access-control-max-age: 86400
date: Thu, 20 Jun 2019 15:18:43 GMT
server: istio-envoy
content-length: 0

Then I configure the following Policy in order to enable Jwt authentication

cat <<EOF | kubectl apply -n foo -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "jwt-httpbinext"
spec:
  targets:
  - name: httpbinext
  origins:
  - jwt:
      issuer: "testing@secure.istio.io"
      jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.1/security/tools/jwt/samples/jwks.json"
  principalBinding: USE_ORIGIN
EOF

However, when I try to access httpbin (via httpbinext.foo.svc.cluster.local) without a token through the ingress controller I am getting 200 while I was expecting 401.

>curl $INGRESS_URL/headers -s -o /dev/null -w '%{http_code}\n' -H 'Host: httpbinext.foo.svc.cluster.local'
200

I repeated the very same test for an internal httpbin service inside k8s (httpbin.foo.svc.cluster.local) and it works as expected

>curl $INGRESS_URL/headers -s -o /dev/null -w '%{http_code}\n' -H 'Host: httpbin.foo.svc.cluster.local'
401

Any help would be appreciated.

We don’t support authentication for services outside the mesh. Authentication is implemented server-side in the service “sidecar” proxy, not the ingress gateway at present.

1 Like

To be correct, we do support ingress in the same way as sidecar, but not for virtual service. In other words, you can set up JWT validation using target name is the ingress service name (e.g istio-ingressgateway). All traffic to ingress (for the intended port) will require JWT. But you cannot distinguish traffic for different virtual service.

1 Like

I have verified that configuring the jwt policy for the istio-system/istio-ingressgateway works globally (with the limitation mentioned above).

>cat <<EOF | kubectl apply -n istio-system -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "jwt-ingress"
spec:
  targets:
  - name: istio-ingressgateway
  origins:
  - jwt:
      issuer: "testing@secure.istio.io"
      jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.1/security/tools/jwt/samples/jwks.json"
  principalBinding: USE_ORIGIN
EOF

Thank you both for your input.