{"id":21354850,"url":"https://github.com/salrashid123/istio_external_authorization_server","last_synced_at":"2025-04-24T03:46:52.890Z","repository":{"id":91310039,"uuid":"245501595","full_name":"salrashid123/istio_external_authorization_server","owner":"salrashid123","description":"Tutorial to setup a simple Istio external authorization server","archived":false,"fork":false,"pushed_at":"2024-11-13T12:51:36.000Z","size":783,"stargazers_count":53,"open_issues_count":3,"forks_count":16,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-24T03:46:47.123Z","etag":null,"topics":["envoyproxy","istio"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/salrashid123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-06T19:33:53.000Z","updated_at":"2024-11-22T21:53:08.000Z","dependencies_parsed_at":"2025-01-09T19:43:12.053Z","dependency_job_id":"8df67659-b7b6-4cc2-b014-b472e9a6b7d9","html_url":"https://github.com/salrashid123/istio_external_authorization_server","commit_stats":{"total_commits":23,"total_committers":1,"mean_commits":23.0,"dds":0.0,"last_synced_commit":"90a8ffeca47424a6856befec7c41ad01936d8ec3"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fistio_external_authorization_server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fistio_external_authorization_server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fistio_external_authorization_server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fistio_external_authorization_server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salrashid123","download_url":"https://codeload.github.com/salrashid123/istio_external_authorization_server/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250560008,"owners_count":21450168,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["envoyproxy","istio"],"created_at":"2024-11-22T04:14:45.131Z","updated_at":"2025-04-24T03:46:52.862Z","avatar_url":"https://github.com/salrashid123.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# External Authorization Server with Istio\n\nTutorial to setup an external authorization server for istio.  In this setup, the `ingresss-gateway` will first send the inbound request headers to another istio service which check the header values submitted by the remote user/client.  If the header values passes some criteria, the external authorization server will instruct the authorization server to proceed with the request upstream.\n\nThe check criteria can be anything (kerberos ticket, custom JWT) but in this example, it is the simple presence of the header value match as defined in configuration.\n\nIn this setup, it is important to ensure the authorization server is always (and exclusively) called by the ingress gateway and that the upstream services must accept the custom JWT token issued by the authorization server.\n\nTo that end, this configuration sets up `mTLS`, `RBAC` and `ORIGIN` authentication.  RBAC ensures service-\u003eservice traffic flows between the gateway, authorization server and the upstream systems.   Each upstream service will only allow `ORIGIN` JWT tokens issued by the authorization server.\n\n\n![images/istio-extauthz.svg](images/istio-extauthz.svg)\n\nThis tutorial is a continuation of the [istio helloworld](https://github.com/salrashid123/istio_helloworld) application.\n\n\u003e\u003e `12/11/24`: Use minikube\n\u003e\u003e `11/25/21`: Updated for example to NOT use an actual service account.  Instead, use the istio built [gen-jwtpy](https://istio.io/v1.10/docs/tasks/security/authentication/authn-policy/#end-user-authentication) in JWT issuers\n\n\u003e\u003e `3/20/21`: Updated for [istio 1.9: Integrate external authorization system (e.g. OPA, oauth2-proxy, etc.) with Istio using AuthorizationPolicy](https://istio.io/latest/blog/2021/better-external-authz/).   Part of the upgrade is to use the `v3` API (`go-control-plane/envoy/config/core/v3`, `go-control-plane/envoy/service/auth/v3`)\n\n### References\n\n- [Envoy External Authorization](https://www.envoyproxy.io/docs/envoy/latest/api-v2/config/filter/http/ext_authz/v2/ext_authz.proto)\n  - [Envoy External Authorization server (envoy.ext_authz) HelloWorld](https://github.com/salrashid123/envoy_external_authz)\n- [Istio Security](https://istio.io/docs/concepts/security/)\n- [External authorization with custom action](https://istio.io/latest/docs/tasks/security/authorization/authz-custom/)\n\n\n### Setup\n\nThe following setup uses a minikube and a convenient JWK endpoint provided by an Istio sample JWT authentication tutorial.\n\nFirst install istio\n\n```bash\nminikube start --driver=kvm2  --cpus=4 --kubernetes-version=v1.28 --host-only-cidr 192.168.39.1/24\nminikube addons enable metallb\n\n## in a new window\nminikube dashboard\n\n## get the IP, for me it was the following\n$ minikube ip\n192.168.39.1\n\n## setup a loadbalancer metallb, enter the ip range shown below\nminikube addons configure metallb\n# -- Enter Load Balancer Start IP: 192.168.39.104\n# -- Enter Load Balancer End IP: 192.168.39.110\n\n## download and install istio\nexport ISTIO_VERSION=1.24.0 \nexport ISTIO_VERSION_MINOR=1.24\n\nwget -P /tmp/ https://github.com/istio/istio/releases/download/$ISTIO_VERSION/istio-$ISTIO_VERSION-linux-amd64.tar.gz\ntar xvf /tmp/istio-$ISTIO_VERSION-linux-amd64.tar.gz -C /tmp/\nrm /tmp/istio-$ISTIO_VERSION-linux-amd64.tar.gz\n\nexport PATH=/tmp/istio-$ISTIO_VERSION/bin:$PATH\n\nistioctl install --set profile=demo \\\n --set meshConfig.enableAutoMtls=true  \\\n --set values.gateways.istio-ingressgateway.runAsRoot=true \\\n --set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY \\\n --set meshConfig.defaultConfig.gatewayTopology.forwardClientCertDetails=SANITIZE_SET \n```\n\n\n### Build and push images\n\nYou can use the following prebuilt containers for this tutorial if you want to. \n\nIf you would rather build and stage your own, the `Dockerfile` for each container is provided in this repo.   \n\nThe images we will use here has the following endpoints enabled:\n\n* `salrashid123/svc`: Frontend service\n  - `/version`:  Displays a static \"version\" number for the image.  If using `salrashid123/svc:1` then the version is `1`. If using `salrashid123/svc:2` the version is `2`\n  - `/backend`:  Makes an HTTP Ret call to the backend service's `/backend` and `/headerz` endpoints.\n\n* `salrashid123/besvc`: Backend Service\n  - `/headerz`: Displays the http headers\n  - `/backend`: Displays the pod name\n\n* `salrashid123/ext-authz-server`: External Authorization gRPC Server\n  - gRPC Authorization server running in namespace `authz-ns` as service `authz`\n  - Authorization server reads an environment variable that lists the set of authorized (eg `authzallowedusers: \"alice,bob\"`)\n    This server will read the \"Authorization: Bearer \u003cusername\u003e\" header value from the incoming request to determine the username \n\n\nTo build your own, create a public dockerhub images with the names specified below:\n\n- Build External Authorization Server (you can ofcourse use your own dockerhub repo!)\n\n```bash\ncd authz_server/\ndocker build -t salrashid123/ext-authz-server .\ndocker push salrashid123/ext-authz-server\n```\n- Build Frontend\n```bash\ncd frontend \ndocker build  --build-arg VER=1 -t salrashid123/svc:1 .\ndocker build  --build-arg VER=2 -t salrashid123/svc:2 .\ndocker push salrashid123/svc:1\ndocker push salrashid123/svc:2\n```\n\n- Build Backend\n```bash\ncd backend\ndocker build  --build-arg VER=1 -t salrashid123/besvc:1 .\ndocker build  --build-arg VER=1 -t salrashid123/besvc:2 .\n\ndocker push salrashid123/besvc:1\ndocker push salrashid123/besvc:2\n```\n\n### Verify istio is installed\n\n```bash\nkubectl label namespace default istio-injection=enabled\nkubectl get no,po,rc,svc,ing,deployment -n istio-system\n```\n\n### Deploy Istio Gateway and services\n\n```bash\nkubectl apply -f istio-lb-certs.yaml\nsleep 10\n## create the ingress gateway\nkubectl apply -f istio-ingress-gateway.yaml\n\n## kill and restart the ingress pod since the LB cert's may not have been loaded\nINGRESS_POD_NAME=$(kubectl get po -n istio-system | grep ingressgateway\\- | awk '{print$1}'); echo ${INGRESS_POD_NAME};\nkubectl delete po/$INGRESS_POD_NAME -n istio-system\n\nkubectl apply -f istio-app-config.yaml\n\nexport GATEWAY_IP=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\necho $GATEWAY_IP\n```\n\n#### Debugging ingress-gateway\n\n```bash\nINGRESS_POD_NAME=$(kubectl get po -n istio-system | grep ingressgateway\\- | awk '{print$1}'); echo ${INGRESS_POD_NAME};\nkubectl exec --namespace=istio-system $INGRESS_POD_NAME -c istio-proxy -- curl -X POST  http://localhost:15000/logging\\?level\\=debug\nkubectl logs $INGRESS_POD_NAME -n istio-system\n```\n\n\n### Deploy application\n\nDeploy the baseline application without the external authorization server\n\n```bash\n$ kubectl apply -f app-deployment.yaml\n\n$ kubectl get po,svc\nNAME                         READY   STATUS    RESTARTS   AGE\npod/be-v1-8589f84d6-ll82f    2/2     Running   0          74s\npod/be-v2-6ff75fccd8-chj92   2/2     Running   0          74s\npod/svc1-bdb4d7c59-fgfk5     2/2     Running   0          74s\npod/svc2-7f65cc98f-hxcw9     2/2     Running   0          74s\n\nNAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE\nservice/be           ClusterIP   10.116.6.105   \u003cnone\u003e        8080/TCP   74s\nservice/kubernetes   ClusterIP   10.116.0.1     \u003cnone\u003e        443/TCP    5m26s\nservice/svc1         ClusterIP   10.116.9.247   \u003cnone\u003e        8080/TCP   75s\nservice/svc2         ClusterIP   10.116.12.54   \u003cnone\u003e        8080/TCP   74s\n```\n\n\n\n### Send Traffic\n\nVerify traffic for the frontend and backend services.  (we're using [jq](https://stedolan.github.io/jq/download/) to help parse the response)\n\n```bash\n# Access the frontend for svc1,svc2\ncurl -s --cacert certs/CA_crt.pem -w \" %{http_code}\\n\" --resolve svc1.example.com:443:$GATEWAY_IP  https://svc1.example.com/version\ncurl -s --cacert certs/CA_crt.pem -w \" %{http_code}\\n\" --resolve svc2.example.com:443:$GATEWAY_IP  https://svc2.example.com/version\n\n# Access the backend through svc1,svc2\ncurl -s --cacert certs/CA_crt.pem -w \" %{http_code}\\n\" --resolve svc1.example.com:443:$GATEWAY_IP  https://svc1.example.com/backend | jq '.'\ncurl -s --cacert certs/CA_crt.pem -w \" %{http_code}\\n\" --resolve svc2.example.com:443:$GATEWAY_IP  https://svc2.example.com/backend | jq '.'\n```\n\nIf you would rather run this in a loop:\n\n```bash\n for i in {1..1000}; do curl -s -w \" %{http_code}\\n\" --cacert certs/CA_crt.pem --resolve svc1.example.com:443:$GATEWAY_IP  https://svc1.example.com/version; sleep 1; done\n```\n\n##### Kiali Dashboard\n\nIf you want, launch the kiali dashboard (default password is `admin/admin`).  In a new window, run:\n\n```bash\necho $ISTIO_VERSION \necho $ISTIO_VERSION_MINOR\nkubectl apply -f https://raw.githubusercontent.com/istio/istio/release-$ISTIO_VERSION_MINOR/samples/addons/prometheus.yaml\nsleep 20\nkubectl apply -f https://raw.githubusercontent.com/istio/istio/release-$ISTIO_VERSION_MINOR/samples/addons/kiali.yaml\nkubectl apply -f https://raw.githubusercontent.com/istio/istio/release-$ISTIO_VERSION_MINOR/samples/addons/grafana.yaml\nkubectl apply -f https://raw.githubusercontent.com/istio/istio/release-$ISTIO_VERSION_MINOR/samples/addons/jaeger.yaml\n\n### in a new window, install prometheus, kaili, jager and grafana\n## open a tunnel and access the kiali dashboard at  http://localhost:20001/kiali (admin/admi)\nkubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app.kubernetes.io/name=kiali -o jsonpath='{.items[0].metadata.name}') 20001:20001\n```\n\n![images/default-traffic.png](images/default-traffic.png)\n\n### Generate Authz config\n\nFirst we need to setup the auth* configs to use a convenient JWT/JWK issuer istio provides (you can use any jWT issuer, ofcourse; this is just a demo...do not use this in production!!!)\n\n##### Use Istio's sample JWT issuer script\n\nIstio provides a convenient JWT issuer, JWK and script the gateway will for authentication. You are certainly supposed to use your own JWK/JWT issuer; we're just using this one since it has a convenient JWK endpoint to verify the tokens with\n\nWe will use following script to issue a JWT and verify the JWK.  This will be the same key that the external authorization server uses.\n\n```bash\nwget --no-verbose https://raw.githubusercontent.com/istio/istio/release-$ISTIO_VERSION_MINOR/security/tools/jwt/samples/gen-jwt.py\nwget --no-verbose https://raw.githubusercontent.com/istio/istio/release-$ISTIO_VERSION_MINOR/security/tools/jwt/samples/key.pem\n\n# may need pip3 install jwcrypto\npython3 gen-jwt.py -aud some.audience -expire 3600 key.pem\n```\n\n```json\n{\n  \"alg\": \"RS256\",\n  \"kid\": \"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ\",\n  \"typ\": \"JWT\"\n}\n\n{\n  \"aud\": \"some.audience\",\n  \"exp\": 1635174518,\n  \"iat\": 1635170918,\n  \"iss\": \"testing@secure.istio.io\",\n  \"sub\": \"testing@secure.istio.io\"\n}\n```\n\nYou can also see that its `kid` key-id is visible too `\"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ\"`\n\nThe JWK endpoint istio will use to validate a JWT issued by the authorization server is:\n\n```json\n$ curl -s https://raw.githubusercontent.com/istio/istio/release-1.10/security/tools/jwt/samples/jwks.json | jq '.'\n{\n  \"keys\": [\n    {\n      \"e\": \"AQAB\",\n      \"kid\": \"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ\",\n      \"kty\": \"RSA\",\n      \"n\": \"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ\"\n    }\n  ]\n}\n```\n\nNOTE: we will not be issuing these JWTs.  The external authorization server will use the private key to reissue a JWT intended for a given service.\n\n\nApply the preset environment variables to  `ext_authz_filter.yaml`:\n\n```bash\nexport SERVICE_ACCOUNT_EMAIL=\"testing@secure.istio.io\"\nwget --no-verbose https://raw.githubusercontent.com/istio/istio/release-$ISTIO_VERSION_MINOR/security/tools/jwt/samples/key.pem\nexport KEY_ID=\"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ\"\nexport SVC_ACCOUNT_KEY=`base64 -w 0 key.pem \u0026\u0026 echo`\n\necho $SERVICE_ACCOUNT_EMAIL\necho $KEY_ID\necho $SVC_ACCOUNT_KEY\n```\n\n### Apply Authz rules\n\n```bash\nenvsubst \u003c \"ext_authz_rules.yaml.tmpl\" \u003e \"ext_authz_rules.yaml\"\nkubectl apply -f ext_authz_rules.yaml\n```\n\nThis will cause a 'deny' for everyone since we specified some headers that cannot be met (since we didnt' even deploy the authzserver in the first place that'd issue the JWT we just declared above!)\n\n\n### Deploy ExtAuthz server \n\nEdit mesh-config\n\n```bash\nkubectl edit configmap istio -n istio-system\n```\n\nappend the section for `extensionProviders` to the top of the `mesh` definition as such (remember to delete the definition of `extensionProviders` already set with `envoyOtelAls`)\n\n```yaml\napiVersion: v1 \ndata: \n  mesh: |-  \n    extensionProviders:\n    - name: \"my-ext-authz-grpc\"\n      envoyExtAuthzGrpc:\n        service: \"authz.authz-ns.svc.cluster.local\"\n        port: \"50051\"\n    - name: otel \n      envoyOtelAls: \n        port: 4317 \n        service: opentelemetry-collector.istio-system.svc.cluster.local \n```\n![images/config_image.png](images/config_img.png)\n\nplease note the name for the provider: `\"my-ext-authz-grpc\"`.  This is defined in the `ext_authz.yaml` provider filter\n\n```yaml\napiVersion: security.istio.io/v1beta1\nkind: AuthorizationPolicy\nmetadata:\n  name: ext-authz\n  namespace: istio-system\nspec:\n  selector:\n    matchLabels:\n      istio: ingressgateway\n  action: CUSTOM\n  provider:\n    name: \"my-ext-authz-grpc\"\n  rules:\n  - to:\n    - operation:\n        paths: [\"/*\"]   \n```\n\nReload the gateway:\n\n```bash\nINGRESS_POD_NAME=$(kubectl get po -n istio-system | grep ingressgateway\\- | awk '{print$1}'); echo ${INGRESS_POD_NAME};\nkubectl delete po/$INGRESS_POD_NAME -n istio-system\n```\n\nApply the authz config\n\n```bash\nenvsubst \u003c \"ext_authz.yaml.tmpl\" \u003e \"ext_authz.yaml\"\nkubectl apply -f ext_authz.yaml\n```\n\n\n```bash\n$ kubectl get PeerAuthentication,RequestAuthentication,AuthorizationPolicy -n authz-ns\nNAME                                                                     MODE     AGE\npeerauthentication.security.istio.io/ing-authzserver-peer-authn-policy   STRICT   13s\n\nNAME                                                                 ACTION   AGE\nauthorizationpolicy.security.istio.io/deny-all-authz-ns                       13s\nauthorizationpolicy.security.istio.io/ing-authzserver-authz-policy   ALLOW    13s\n\n$ kubectl get PeerAuthentication,RequestAuthentication,AuthorizationPolicy -n default\nNAME                                                                     AGE\nrequestauthentication.security.istio.io/ing-svc1-request-authn-policy    109s\nrequestauthentication.security.istio.io/ing-svc2-request-authn-policy    109s\nrequestauthentication.security.istio.io/svc-be-v1-request-authn-policy   109s\nrequestauthentication.security.istio.io/svc-be-v2-request-authn-policy   109s\n\nNAME                                                            ACTION   AGE\nauthorizationpolicy.security.istio.io/deny-all-default                   109s\nauthorizationpolicy.security.istio.io/ing-svc1-authz-policy     ALLOW    109s\nauthorizationpolicy.security.istio.io/ing-svc2-authz-policy     ALLOW    109s\nauthorizationpolicy.security.istio.io/svc1-be-v1-authz-policy   ALLOW    109s\nauthorizationpolicy.security.istio.io/svc1-be-v2-authz-policy   ALLOW    109s\n\n```\n\n### Access Frontend\n\nThe static/demo configuration here uses two users (`alice`, `bob`), two frontend services (`svc1`,`svc2`) one backend service with two labled versions (`be`, `version=v1`,`version=v2`).\n\nThe following conditions are coded into the authorization server:\n\n- If the authorization server sees `alice`, it issues a JWT token with `svc1` and `be` as the targets (multiple audiences)\n- If the authorization server sees `bob`, it issues a JWT token with `svc2` as the target\n- If the authorization server sees `carol`, it issues a JWT token with `svc1` as the target only.\n\n```golang\nvar aud []string\nif token == \"alice\" {\n\taud = []string{\"http://svc1.default.svc.cluster.local:8080/\", \"http://be.default.svc.cluster.local:8080/\"}\n} else if token == \"bob\" {\n\taud = []string{\"http://svc2.default.svc.cluster.local:8080/\"}\n} else if token == \"carol\" {\n\taud = []string{\"http://svc1.default.svc.cluster.local:8080/\"}\n} else {\n\taud = []string{}\n}\n```\n\nThe net effect of that is `alice` can view `svc1`, `bob` can view `svc2` using `ORIGIN` authentication.\n\nAs Alice:\n\n```bash\nexport USER=alice\n\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc1.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc1.example.com/version\n\n\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc2.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc2.example.com/version\n```\n\n```\n\u003e\u003e\u003e 1 200\n\u003e\u003e\u003e Audiences in Jwt are not allowed 403\n```\n\nIf you want to view the authz logs\n\n```bash\nAUTHZ_POD_NAME=$(kubectl get po -n authz-ns | grep authz\\- | awk '{print$1}'); echo ${AUTHZ_POD_NAME};\n\nkubectl logs -n authz-ns $AUTHZ_POD_NAME -c authz-container\n```\nYou should see some debug logs as well as the actual reissued JWT header\n\n```log\n2024/11/13 12:33:41 Starting gRPC Server at :50051\n2024/11/13 12:34:01 \u003e\u003e\u003e Authorization called check()\n2024/11/13 12:34:01 Authorization Header Bearer alice\n2024/11/13 12:34:01 Using Claim {alice [http://svc1.default.svc.cluster.local:8080/ http://be.default.svc.cluster.local:8080/] {testing@secure.istio.io testing@secure.istio.io [] 2024-11-13 12:35:01.446845225 +0000 UTC m=+79.858574856 \u003cnil\u003e 2024-11-13 12:34:01.446845119 +0000 UTC m=+19.858574750 }}\n2024/11/13 12:34:01 Issuing outbound Header eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJ1aWQiOiJhbGljZSIsImF1ZCI6WyJodHRwOi8vc3ZjMS5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsOjgwODAvIiwiaHR0cDovL2JlLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWw6ODA4MC8iXSwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyIsImV4cCI6MTczMTUwMTMwMSwiaWF0IjoxNzMxNTAxMjQxfQ.Q-itZwt9AkSjpR3JjHxAyMMdhUOMwythPdB3IH-kZspwP4PH87BGyKNs71WzRqTCbOkd9U9EoiGEO16blV_EFpBQHKkHCIp-T070D2eyJu262MXr3tCwsrp0YHl-tx7qyICoLtMe77LNduI8bWj_2Q61fwALnAOslyH0Cj47u7Gq1FQ0-dFXssR8oMXM8eNSaF30oU2SHf_FGrd56TgJ8gCcl0Qhik6qC11ihjKl8S3_ccw1D48iCX8JlA8cWR5JMTqHhwQEEdTZtMJAR7HB0DuSAMKxWu2ENuyE6_lLDQmbLPbwTW6dy1nJa4JQGA9Eo6JtfWf3FHlAc7QuFfvz3Q\n2024/11/13 12:34:01 \u003e\u003e\u003e Authorization called check()\n2024/11/13 12:34:01 Authorization Header Bearer alice\n2024/11/13 12:34:01 Using Claim {alice [http://svc1.default.svc.cluster.local:8080/ http://be.default.svc.cluster.local:8080/] {testing@secure.istio.io testing@secure.istio.io [] 2024-11-13 12:35:01.504861628 +0000 UTC m=+79.916591235 \u003cnil\u003e 2024-11-13 12:34:01.50486156 +0000 UTC m=+19.916591168 }}\n2024/11/13 12:34:01 Issuing outbound Header eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJ1aWQiOiJhbGljZSIsImF1ZCI6WyJodHRwOi8vc3ZjMS5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsOjgwODAvIiwiaHR0cDovL2JlLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWw6ODA4MC8iXSwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyIsImV4cCI6MTczMTUwMTMwMSwiaWF0IjoxNzMxNTAxMjQxfQ.Q-itZwt9AkSjpR3JjHxAyMMdhUOMwythPdB3IH-kZspwP4PH87BGyKNs71WzRqTCbOkd9U9EoiGEO16blV_EFpBQHKkHCIp-T070D2eyJu262MXr3tCwsrp0YHl-tx7qyICoLtMe77LNduI8bWj_2Q61fwALnAOslyH0Cj47u7Gq1FQ0-dFXssR8oMXM8eNSaF30oU2SHf_FGrd56TgJ8gCcl0Qhik6qC11ihjKl8S3_ccw1D48iCX8JlA8cWR5JMTqHhwQEEdTZtMJAR7HB0DuSAMKxWu2ENuyE6_lLDQmbLPbwTW6dy1nJa4JQGA9Eo6JtfWf3FHlAc7QuFfvz3Q\n\n```\n\nnote JWT headers include cliams and audiences\n\n```json\n{\n  \"alg\": \"RS256\",\n  \"kid\": \"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ\",\n  \"typ\": \"JWT\"\n}\n\n{\n  \"uid\": \"alice\",\n  \"aud\": [\n    \"http://svc1.default.svc.cluster.local:8080/\",\n    \"http://be.default.svc.cluster.local:8080/\"\n  ],\n  \"exp\": 1635173568,\n  \"iat\": 1635173508,\n  \"iss\": \"testing@secure.istio.io\",\n  \"sub\": \"testing@secure.istio.io\"\n}\n```\n\nAs Bob:\n\n```bash\nexport USER=bob\n\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc1.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc1.example.com/version\n\n\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc2.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc2.example.com/version\n```\n\n```\n\u003e\u003e\u003e Audiences in Jwt are not allowed 403\n\u003e\u003e\u003e 2 200\n```\n\nAs Carol\n\n```bash\nexport USER=carol\n\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc1.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc1.example.com/version\n\n\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc2.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc2.example.com/version\n```\n\n```\n\u003e\u003e\u003e 1 200\n\u003e\u003e\u003e Audiences in Jwt are not allowed 403\n```\n\n![images/authz_ns_flow_fe.png](images/authz_ns_flow_fe.png)\n\n\u003e\u003e note, it seems the traffic from the gateway to the authorization server isn't correctly detected to be associated with the ingress-gateway (maybe a bug or some label is missing)\n\n### Access Backend\n\nThe configuration also defines Authorization policies on the `svc1`-\u003e `be` traffic using **BOTH** `PEER` and `ORIGIN`. \n\n- `PEER`:\n\nThis is done using normal RBAC service identities:\n\n```yaml\napiVersion: security.istio.io/v1\nkind: AuthorizationPolicy\nmetadata:\n name: svc1-be-v1-authz-policy\n namespace: default\nspec:\n action: ALLOW\n selector:\n   matchLabels:\n     app: be\n     version: v1\n rules:\n - from:\n   - source:\n       principals: [\"cluster.local/ns/default/sa/svc1-sa\"]\n   to:\n   - operation:\n       methods: [\"GET\"]\n```\n\n#### Backend PEER and ORIGIN\n\nNote the `from-\u003esource-\u003eprincipals` denotes  the service account `svc1` runs as.\n\n- `ORIGIN`\n\nTHis step is pretty unusual and requires some changes to application code to _forward_ its inbound authentication token. \n\nRecall the inbound JWT token to `svc1` for `alice` includes two audiences:\n\n```golang\n\taud = []string{\"http://svc1.default.svc.cluster.local:8080/\", \"http://be.default.svc.cluster.local:8080/\"}\n```\n\nThis means we can use the same JWT token on the backend service if we setup an authentication and authz rule:\n\n```yaml\n## svc --\u003e be-v1\napiVersion: security.istio.io/v1\nkind: RequestAuthentication\nmetadata:\n name: svc-be-v1-request-authn-policy\n namespace: default\nspec:\n  selector:\n    matchLabels:\n      app: be\n      version: v1\n  jwtRules:\n  - issuer: \"$SERVICE_ACCOUNT_EMAIL\"\n    audiences:\n    - \"http://be.default.svc.cluster.local:8080/\"   \n    jwksUri: \"https://raw.githubusercontent.com/istio/istio/release-$ISTIO_VERSION_MINOR/security/tools/jwt/samples/jwks.json\" \n    outputPayloadToHeader: x-jwt-payload  \n---\napiVersion: security.istio.io/v1\nkind: AuthorizationPolicy\nmetadata:\n name: svc1-be-v1-authz-policy\n namespace: default\nspec:\n action: ALLOW\n selector:\n   matchLabels:\n     app: be\n     version: v1\n rules:\n - from:\n   - source:\n       principals: [\"cluster.local/ns/default/sa/svc1-sa\"]\n   to:\n   - operation:\n       methods: [\"GET\"]\n   when:\n   - key: request.auth.claims[iss]\n     values: [\"$SERVICE_ACCOUNT_EMAIL\"]\n   - key: request.auth.claims[aud]\n     values: [\"http://be.default.svc.cluster.local:8080/\"]   \n```\n\nThe `RequestAuthentication` accepts a JWT token signed by the external authz server and must also include the audience of the backend (which alice's token has).  The second authorization (redundantly) rule further parses out the token and looks for the same.\n\nIstio does not automatically forward the inbound token (though it maybe possible with `SIDECAR_INBOUND`-\u003e`SIDECAR_OUTBOUND` forwarding somehow...)...to achieve this requres some application code changes.  The folloing snippet is the code within `frontend/app.js` which take the token and uses it on the backend api call. \n\n\u003e\u003e `4/27/20`: update on the comment \"(though it maybe possble with `SIDECAR_INBOUND`-\u003e`SIDECAR_OUTBOUND` forwarding somehow...)\"   Its not; envoy doens't carry state from the filters forward like this.  You need to either accept and forward the header in code as shown below:\n\n```javascript\nvar resp_promises = []\nvar urls = [\n            'http://' + host + ':' + port + '/backend',\n            'http://' + host + ':' + port + '/headerz',\n]\n\nout_headers = {};\nif (FORWARD_AUTH_HEADER == 'true') {\n    var auth_header = request.headers['authorization']; \n    logger.info(\"Got Authorization Header: [\" + auth_header + \"]\");\n      out_headers = {\n          'authorization':  auth_header,\n      };\n    }\n\nurls.forEach(element =\u003e {\n     resp_promises.push( getURL(element,out_headers) )\n});\n```\n\nOr configure istio to make an `OUTBOUND` ext_authz filter call.  The external authz filter will return a new Authorization server token intended for ust `svcb`.\n\nYou will also need to set [allowed_client_headers](https://www.envoyproxy.io/docs/envoy/latest/api-v2/config/filter/http/ext_authz/v2/ext_authz.proto#envoy-api-msg-config-filter-http-ext-authz-v2-authorizationresponse) so that the auth token returned by ext-authz server is sent to the upstream (in this case, upstream is `svcb`)\n\nI think the config would be _something_ like this:\n\n```yaml\napiVersion: networking.istio.io/v1\nkind: EnvoyFilter\nmetadata:\n  name: ext-authz-service\n  namespace: default\nspec:\n  workloadLabels:\n    app: svc1\n  filters:\n  - listenerMatch:\n      listenerType: OUTBOUND    #  \u003c\u003c\u003c\u003c  OUTBOUND svc1-\u003e*  \n      listenerProtocol: HTTP \n    insertPosition:\n      index: FIRST           \n    filterName: envoy.ext_authz\n    filterType: HTTP\n    filterConfig:\n      grpc_service:\n        envoy_grpc:\n          cluster_name: patched.authz.authz-ns.svc.cluster.local      \n          authorization_response:\n            allowed_client_headers:\n              patterns:\n                - exact: \"Authorization\"\n```\n(ofcourse changes are needed to ext-authz server as provided in this repo..)\n\n\u003e\u003e Note: i added both ORIGIN and PEER just to demonstrate this...Until its easier forward the token by envoy/istio, i woudn't recommend doing  this bit..\n\n\nAnwyay, to test all this out\n\n```bash\nexport USER=alice\n\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc1.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc1.example.com/backend | jq '.'\n\n\nexport USER=bob\n\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc2.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc2.example.com/backend | jq '.'\n\nexport USER=carol\n\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc1.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc1.example.com/backend | jq '.'\n```\n\nSample output\n\n-Alice\n\nAlice's TOKEN issued by the authorization server includes two audiences:\n\n```golang\naud = []string{\"http://svc1.default.svc.cluster.local:8080/\", \"http://be.default.svc.cluster.local:8080/\"}\n```\n\nWhich is allowed by backend services `RequestAuthentication` policy.\n\n```bash\nexport USER=alice\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc1.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc1.example.com/backend | jq '.'\n\n[\n  {\n    \"url\": \"http://be.default.svc.cluster.local:8080/backend\",\n    \"body\": \"pod: [be-v2-64d9cf5fb4-mpsq5]    node: [gke-istio-1-default-pool-b516bc56-xz2c]\",\n    \"statusCode\": 200\n  },\n  {\n    \"url\": \"http://be.default.svc.cluster.local:8080/headerz\",\n    \"body\": \"{\\\"host\\\":\\\"be.default.svc.cluster.local:8080\\\",\\\"x-forwarded-proto\\\":\\\"http\\\",\\\"x-request-id\\\":\\\"bb31942c-f04e-9b12-ba69-d68603a520af\\\",\\\"content-length\\\":\\\"0\\\",\\\"x-forwarded-client-cert\\\":\\\"By=spiffe://cluster.local/ns/default/sa/be-sa;Hash=2e0f9ca7bea6ac081f4c256de79ffdb4db2e55968b0ded2526e95cb89f4c36ac;Subject=\\\\\\\"\\\\\\\";URI=spiffe://cluster.local/ns/default/sa/svc1-sa\\\",\\\"x-b3-traceid\\\":\\\"cda6d87c8d342998ee1f797471592dff\\\",\\\"x-b3-spanid\\\":\\\"6dc54e848db21050\\\",\\\"x-b3-parentspanid\\\":\\\"ee1f797471592dff\\\",\\\"x-b3-sampled\\\":\\\"1\\\"}\",\n    \"statusCode\": 200\n  }\n]\n```\n\n- Bob\n\nBob's token does not include the backend service \n\n```golang\naud = []string{\"http://svc2.default.svc.cluster.local:8080/\"}\n```\n\nWhich means the `RequestAuthentication` will fail.  Bob is only allowed to invoke `svc2` anyway\n\n\n```bash\nexport USER=bob\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc2.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc2.example.com/backend  | jq '.'\n\n[\n  {\n    \"url\": \"http://be.default.svc.cluster.local:8080/backend\",\n    \"body\": \"Audiences in Jwt are not allowed\",\n    \"statusCode\": 403\n  },\n  {\n    \"url\": \"http://be.default.svc.cluster.local:8080/headerz\",\n    \"body\": \"Audiences in Jwt are not allowed\",\n    \"statusCode\": 403\n  }\n]\n```\n\n- Carol\n\nCarol's token is allowed to invoke `svc1` but does not include the issuer to pass the `RequestAuthentication` policy\n\n```golang\naud = []string{\"http://svc1.default.svc.cluster.local:8080/\"}\n```\n\n```bash\nexport USER=carol\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc1.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc1.example.com/backend | jq '.'\n\n[\n  {\n    \"url\": \"http://be.default.svc.cluster.local:8080/backend\",\n    \"body\": \"Audiences in Jwt are not allowed\",\n    \"statusCode\": 403\n  },\n  {\n    \"url\": \"http://be.default.svc.cluster.local:8080/headerz\",\n    \"body\": \"Audiences in Jwt are not allowed\",\n    \"statusCode\": 403\n  }\n]\n```\n\n![images/authz_ns_flow_fe.png](images/authz_ns_flow_fe.png)\n\n\nIf you would rather run these tests in a loop\n```bash\n for i in {1..1000}; do curl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc1.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc1.example.com/version; sleep 1; done\n```\n\n---\n\nAt this point, the system is setup to to always use mTLS, `ORIGIN` and `PEER` authentication plus `RBAC`.  If you want to verify any component of `PEER`, change the policy and change the service account that is the target service authorization policy accepts and reapply the config.  \n\nChange either the settings `RequestAuthentication` _or_  `AuthorizationPolicy` depending on which layer you are testing\n\n(remember to replace the value for `$ISTIO_VERSION_MINOR` )\n\n```yaml\n## svc --\u003e be-v1\napiVersion: security.istio.io/v1\nkind: RequestAuthentication\nmetadata:\n name: svc-be-v1-request-authn-policy\n namespace: default\nspec:\n  selector:\n    matchLabels:\n      app: be\n      version: v1\n  jwtRules:\n  - issuer: \"$SERVICE_ACCOUNT_EMAIL\"\n    audiences:\n    - \"http://be.default.svc.cluster.local:8080/\"      ##  or CHANGE ORIGIN  \u003c\u003c\u003c\u003c  \"Audiences in Jwt are not allowed\"\n    jwksUri: \"https://raw.githubusercontent.com/istio/istio/release-$ISTIO_VERSION_MINOR/security/tools/jwt/samples/jwks.json\"  \n    # forwardOriginalToken: true\n    outputPayloadToHeader: x-jwt-payload   \n---\n## svc --\u003e be-v2\napiVersion: security.istio.io/v1\nkind: RequestAuthentication\nmetadata:\n name: svc-be-v2-request-authn-policy\n namespace: default\nspec:\n  selector:\n    matchLabels:\n      app: be\n      version: v2\n  jwtRules:\n  - issuer: \"$SERVICE_ACCOUNT_EMAIL\"\n    audiences:\n    - \"http://be.default.svc.cluster.local:8080/\"   ##  or CHANGE ORIGIN  \u003c\u003c\u003c\u003c  \"Audiences in Jwt are not allowed\"\n    jwksUri: \"https://raw.githubusercontent.com/istio/istio/release-$ISTIO_VERSION_MINOR/security/tools/jwt/samples/jwks.json\"\n    # forwardOriginalToken: true\n    outputPayloadToHeader: x-jwt-payload\n---\napiVersion: security.istio.io/v1beta1\nkind: AuthorizationPolicy\nmetadata:\n name: svc1-be-v1-authz-policy\n namespace: default\nspec:\n action: ALLOW\n selector:\n   matchLabels:\n     app: be\n     version: v1\n rules:\n - from:\n   - source:\n       principals: [\"cluster.local/ns/default/sa/svc1-sa\"]    #  CHANGE  PEER  \u003c\u003c\u003c\u003c  \"RBAC: access denied\"\n   to:\n   - operation:\n       methods: [\"GET\"]\n   when:\n   - key: request.auth.claims[iss]\n     values: [\"$SERVICE_ACCOUNT_EMAIL\"]        ##  or CHANGE ORIGIN at Authz \u003c\u003c\u003c\u003c  \"RBAC: access denied\"\n   - key: request.auth.claims[aud]\n     values: [\"http://be.default.svc.cluster.local:8080/\"]          \n---\napiVersion: security.istio.io/v1\nkind: AuthorizationPolicy\nmetadata:\n name: svc1-be-v2-authz-policy\n namespace: default\nspec:\n action: ALLOW\n selector:\n   matchLabels:\n     app: be\n     version: v2\n rules:\n - from:\n   - source:\n       principals: [\"cluster.local/ns/default/sa/svc1-sa\"]   # CHANGE PEER \u003c\u003c\u003c\u003c  \"RBAC: access denied\"\n   to:\n   - operation:\n       methods: [\"GET\"]\n   when:\n   - key: request.auth.claims[iss]\n     values: [\"$SERVICE_ACCOUNT_EMAIL\"]        ##  or CHANGE ORIGIN at Authz \u003c\u003c\u003c\u003c  \"RBAC: access denied\"\n   - key: request.auth.claims[aud]\n     values: [\"http://be.default.svc.cluster.local:8080/\"]            \n```\nthen reapply the config and access the backend as `alice`\n\n```bash\nexport USER=alice\ncurl -s \\\n  --cacert certs/CA_crt.pem  --resolve svc1.example.com:443:$GATEWAY_IP \\\n  -H \"Authorization: Bearer $USER\" \\\n  -w \" %{http_code}\\n\"  \\\n   https://svc1.example.com/backend | jq '.'\n\n\n[\n  {\n    \"url\": \"http://be.default.svc.cluster.local:8080/backend\",\n    \"body\": \"RBAC: access denied\",\n    \"statusCode\": 403\n  },\n  {\n    \"url\": \"http://be.default.svc.cluster.local:8080/headerz\",\n    \"body\": \"RBAC: access denied\",\n    \"statusCode\": 403\n  }\n]\n```\n\nFinally, the external server is attached to the ingress gateway but you could also attach it to a sidecar for an endpoint.  In this mode, the authorization decision is done not at the ingress gateway but locally on a service's sidecar.  To use that mode, define the `EnvoyFilter` workloadLabel and listenerType. eg:\n\n```yaml\napiVersion: networking.istio.io/v1\nkind: EnvoyFilter\nmetadata:\n  name: svc1-authz-filter\n  namespace: default\nspec:\n  workloadSelector:\n    labels:\n      app: svc1\n  configPatches:\n    - applyTo: HTTP_FILTER\n      match:\n        context: SIDECAR_INBOUND\n        listener:\n          filterChain:\n            filter:\n              name: \"envoy.filters.network.http_connection_manager\"\n              subFilter:\n                name: \"envoy.filters.http.router\"\n      patch:\n        operation: INSERT_FIRST\n        value:\n         name: \"envoy.filters.http.ext_authz\"\n         config:\n           grpc_service:\n             envoy_grpc:\n               cluster_name: patched.authz.authz-ns.svc.cluster.local\n```\n\nIf you do this, you will have to setup PEER policies that allow the service to connect and use the authorization server.\n\n---\n\n### Debugging\n\nYou can debug issues using these resources\n\n- [Debugging Envoy and Istio](https://istio.io/docs/ops/diagnostic-tools/proxy-cmd/)\n- [Security Problems](https://istio.io/docs/ops/common-problems/security-issues/)\n\nTo set the log level higher and inspect a pod's logs:\n\n```bash\nistioctl manifest apply --set values.global.proxy.accessLogFile=\"/dev/stdout\"\n```\n\n- Ingress pod\n\n```bash\nINGRESS_POD_NAME=$(kubectl get po -n istio-system | grep ingressgateway\\- | awk '{print$1}'); echo ${INGRESS_POD_NAME};\n\nkubectl exec -ti $INGRESS_POD_NAME -n istio-syste -- /bin/bash\nistioctl proxy-config log  $INGRESS_POD_NAME --level debug\nkubectl logs -f --tail=0 $INGRESS_POD_NAME -n istio-system\nistioctl dashboard envoy $INGRESS_POD_NAME.istio-system\nistioctl experimental  authz check  $INGRESS_POD_NAME.istio-system\n```\n\n```bash\n$ istioctl experimental  authz check  $INGRESS_POD_NAME.istio-system\nChecked 2/2 listeners with node IP 10.48.2.5.\nLISTENER[FilterChain]     CERTIFICATE                                 mTLS (MODE)     JWT (ISSUERS)     AuthZ (RULES)\n0.0.0.0_80                none                                        no (none)       no (none)         no (none)\n0.0.0.0_443               /etc/istio/ingressgateway-certs/tls.crt     no (none)       no (none)         no (none)\n\n$ istioctl authn tls-check  $INGRESS_POD_NAME.istio-system authz.authz-ns.svc.cluster.local\nHOST:PORT                                  STATUS     SERVER     CLIENT     AUTHN POLICY     DESTINATION RULE\nauthz.authz-ns.svc.cluster.local:50051     AUTO       STRICT     -          /default         -\n```\n\n- Authz pod\n\n```bash\nAUTHZ_POD_NAME=$(kubectl get po -n authz-ns | grep authz\\- | awk '{print$1}'); echo ${AUTHZ_POD_NAME};\nistioctl proxy-config log  $AUTHZ_POD_NAME -n authz-ns  --level debug\nkubectl logs -f --tail=0 $AUTHZ_POD_NAME -c authz-container -n  authz-ns\nistioctl dashboard envoy $AUTHZ_POD_NAME.authz-ns\nistioctl experimental  authz check $AUTHZ_POD_NAME.authz-ns\n```\n\n- SVC1 pod\n\n```bash\nSVC1_POD_NAME=$(kubectl get po -n default | grep svc1\\- | awk '{print$1}'); echo ${SVC1_POD_NAME};\n\n$ istioctl authn tls-check  $SVC1_POD_NAME.default be.default.svc.cluster.local\nHOST:PORT                             STATUS     SERVER     CLIENT           AUTHN POLICY     DESTINATION RULE\nbe.default.svc.cluster.local:8080     OK         STRICT     ISTIO_MUTUAL     /default         default/be-destination\n```\n\n- SVC2 pod\n\n```bash\nSVC2_POD_NAME=$(kubectl get po -n default | grep svc2\\- | awk '{print$1}'); echo ${SVC2_POD_NAME};\n\n$ istioctl authn tls-check  $SVC2_POD_NAME.default be.default.svc.cluster.local\nHOST:PORT                             STATUS     SERVER     CLIENT           AUTHN POLICY     DESTINATION RULE\nbe.default.svc.cluster.local:8080     OK         STRICT     ISTIO_MUTUAL     /default         default/be-destination\n```\n\n### Using Google OIDC ORIGIN authentication at Ingress\n\nIf you want to use OIDC JWT authentication at the ingress gateway and then have that token forwarded to the\nexternal authz service, apply the `RequestAuthentication` policies on the ingress gateway  as shown in the equivalent\nEnvoy configuration [here](https://github.com/salrashid123/envoy_iap/blob/master/envoy_google.yaml#L32).\nYou can generate an `id-token` using the script found under `jwt_client/` folder.\n\n### Debugging\n\n```bash\nkubectl get pods -n istio-system -o name -l istio=ingressgateway | sed 's|pod/||' | while read -r pod; do istioctl proxy-config log \"$pod\" -n istio-system --level rbac:debug; done\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fistio_external_authorization_server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalrashid123%2Fistio_external_authorization_server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fistio_external_authorization_server/lists"}