<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>istio request authorization on Digi Hunch</title><link>https://static.digihunch.com/tag/istio-request-authorization/</link><description>Recent content in istio request authorization on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Wed, 02 Apr 2025 13:21:12 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/istio-request-authorization/index.xml" rel="self" type="application/rss+xml"/><item><title>Istio External Authorization via OIDC</title><link>https://static.digihunch.com/2022/02/istio-external-authorization/</link><pubDate>Fri, 25 Feb 2022 01:29:00 -0400</pubDate><guid>https://static.digihunch.com/2022/02/istio-external-authorization/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-istio-external-auth.webp" alt="Featured image of post Istio External Authorization via OIDC" /&gt;&lt;p class="wp-block-paragraph" id="aa"&gt;Istio service mesh allows application developers to offload non-core features to infrastructure layer. We explored authentication and authorization with &lt;a href="https://static.digihunch.com/2022/02/authentication-and-authorization-with-istio/"&gt;Istio&lt;/a&gt; in a basic &lt;a href="https://static.digihunch.com/2022/02/istio-lab-authentication-and-authorization-in-jwt/"&gt;lab&lt;/a&gt;. In this post we continue to explore its capabilities with OIDC integration. This capability is made available thanks to the CUSTOM action in authorization policy, supported since the &lt;a href="https://istio.io/latest/blog/2021/better-external-authz/"&gt;release&lt;/a&gt; of 1.9. It enables any workload on Istio to integrate with an external IAM solution.&lt;/p&gt;&#10;&lt;p class="has-text-align-center wp-block-paragraph"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="461px" viewBox="-0.5 -0.5 461 261" style="max-width:100%;max-height:261px;"&gt;&lt;defs&gt;&lt;/defs&gt;&lt;g&gt;&lt;rect x="0" y="0" width="460" height="260" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;rect x="160" y="10" width="290" height="230" fill="#f5f5f5" stroke="#666666" pointer-events="all"&gt;&lt;/rect&gt;&lt;rect x="240" y="50" width="90" height="40" rx="6" ry="6" fill="#fff2cc" stroke="#d6b656" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 70px; margin-left: 241px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Authorization&lt;br&gt;Policy&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="285" y="74" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Authorization&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;ellipse cx="45" cy="56.25" rx="7.5" ry="6.25" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/ellipse&gt;&lt;path d="M 45 62.5 L 45 83.33 M 45 66.67 L 30 66.67 M 45 66.67 L 60 66.67 M 45 83.33 L 30 100 M 45 83.33 L 60 100" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 107px; margin-left: 45px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"&gt;User&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="45" y="119" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;User&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="150" y="50" width="60" height="40" rx="6" ry="6" fill="#fff2cc" stroke="#d6b656" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 70px; margin-left: 151px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Istio&lt;br&gt;Ingress&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="180" y="74" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Istio&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="240" y="116.15" width="90" height="40" rx="6" ry="6" fill="#fff2cc" stroke="#d6b656" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 136px; margin-left: 241px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;External &lt;br&gt;Authorization&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="285" y="140" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;External&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="240" y="190" width="90" height="40" rx="6" ry="6" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 210px; margin-left: 241px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;OAuth2-Proxy&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="285" y="214" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;OAuth2-Proxy&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="360" y="50" width="80" height="40" rx="6" ry="6" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 70px; margin-left: 361px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;App&lt;br&gt;HelloWorld&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="400" y="74" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;App&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 285 109.78 L 285 96.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 285 115.03 L 281.5 108.03 L 285 109.78 L 288.5 108.03 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 285 91.12 L 288.5 98.12 L 285 96.37 L 281.5 98.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 285 183.63 L 285 162.52" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 285 188.88 L 281.5 181.88 L 285 183.63 L 288.5 181.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 285 157.27 L 288.5 164.27 L 285 162.52 L 281.5 164.27 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 336.37 70 L 353.63 70" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 331.12 70 L 338.12 66.5 L 336.37 70 L 338.12 73.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 358.88 70 L 351.88 73.5 L 353.63 70 L 351.88 66.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 216.37 70 L 233.63 70" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 211.12 70 L 218.12 66.5 L 216.37 70 L 218.12 73.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 238.88 70 L 231.88 73.5 L 233.63 70 L 231.88 66.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 60 70 L 143.63 70" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 148.88 70 L 141.88 73.5 L 143.63 70 L 141.88 66.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;image x="389.5" y="181.5" width="50" height="48" xlink:href="https://app.diagrams.net/img/lib/mscae/Kubernetes.svg"&gt;&lt;/image&gt;&lt;rect x="10" y="190" width="90" height="40" rx="1" ry="1" fill="#000000" stroke="#000000" pointer-events="all" transform="translate(2,3)" opacity="0.25"&gt;&lt;/rect&gt;&lt;rect x="10" y="190" width="90" height="40" rx="1" ry="1" fill="rgb(255, 255, 255)" stroke="#dddddd" pointer-events="all"&gt;&lt;/rect&gt;&lt;path d="M 31.19 223.26 C 30.2 223.26 29.26 222.72 28.77 221.7 L 23 211.3 C 22.48 210.39 22.56 209.33 23 208.58 L 28.82 198.17 C 29.31 197.23 30.2 196.74 31.09 196.74 L 42.78 196.74 C 43.65 196.74 44.51 197.18 45.02 198.07 L 50.82 208.46 C 51.52 209.56 51.28 210.73 50.88 211.38 L 45.12 221.72 C 44.73 222.55 43.86 223.26 42.74 223.26 Z" fill="#5184f3" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 41.44 223.26 L 33.89 215.48 L 32.68 211.94 L 34.3 205.58 L 42.6 205.49 L 49.93 213.1 L 45.12 221.72 C 44.73 222.55 43.86 223.26 42.74 223.26 Z" fill-opacity="0.07" fill="#000000" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;rect x="22.48" y="196.74" width="0" height="0" fill="none" stroke="none" pointer-events="all"&gt;&lt;/rect&gt;&lt;path d="M 36.95 209.34 C 38.04 209.34 38.71 208.38 38.71 207.64 C 38.71 206.52 37.86 205.74 36.98 205.74 C 36.06 205.74 35.16 206.56 35.16 207.52 C 35.16 208.64 36.17 209.34 36.95 209.34 Z M 36.98 216.03 C 38.51 215.44 39.9 214.32 40.31 213.22 L 40.31 212.32 C 40.31 211.22 38.41 210.25 36.97 210.25 C 35.72 210.25 33.63 211.16 33.63 212.28 L 33.63 213.43 C 34.4 214.59 35.59 215.54 36.98 216.03 Z M 36.95 217.2 C 35.55 216.86 34.19 215.98 33.25 214.79 C 32.09 213.42 31.32 211.66 31.32 209.87 L 31.32 205.51 L 36.97 202.92 L 42.6 205.49 L 42.61 209.31 C 42.61 211.3 42.02 213.07 40.9 214.43 C 40.05 215.67 38.84 216.74 36.95 217.2 Z" fill="#ffffff" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 210px; margin-left: 66px;"&gt;&lt;div data-drawio-colors="color: #999999; " style="box-sizing: border-box; font-size: 0px; text-align: left;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(153, 153, 153); line-height: 1.2; pointer-events: all; white-space: nowrap;"&gt;GCP&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="66" y="214" fill="#999999" font-family="Helvetica" font-size="12px"&gt;GCP&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 106.37 210 L 233.63 210" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 101.12 210 L 108.12 206.5 L 106.37 210 L 108.12 213.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 238.88 210 L 231.88 213.5 L 233.63 210 L 231.88 206.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;image x="164.5" y="109.5" width="30" height="46.15" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnY9Imh0dHBzOi8vdmVjdGEuaW8vbmFubyIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIyNDAiIHZpZXdCb3g9IjAgMCAxNjAgMjQwIj4mI3hhOwk8c3R5bGUgdHlwZT0idGV4dC9jc3MiPiYjeGE7CS5zdDB7ZmlsbDojNDY2YmIwO30mI3hhOwk8L3N0eWxlPiYjeGE7CTxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik02MCAyNDBMMCAyMTBoMTYwem0wLTE2MEwwIDIwMGw2MC0xMHpNNzAgMHYxOTBsOTAgMTB6Ii8+JiN4YTs8L3N2Zz4=" preserveAspectRatio="none"&gt;&lt;/image&gt;&lt;rect x="160" y="10" width="140" height="30" fill="none" stroke="none" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 25px; margin-left: 161px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;demo1.digihunch.com&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="230" y="29" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;demo1.digihunch.com&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;switch&gt;&lt;g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;/g&gt;&lt;a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank" rel="noopener"&gt;&lt;text text-anchor="middle" font-size="10px" x="50%" y="100%"&gt;Text is not SVG &amp;#8211; cannot display&lt;/text&gt;&lt;/a&gt;&lt;/switch&gt;&lt;/svg&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph" id="aa"&gt;The rest of this post, provides the step-by-step instruction to configure OIDC integration, based on Istio&amp;#8217;s &lt;a href="https://istio.io/latest/docs/tasks/security/authorization/authz-custom/"&gt;External Authorization&lt;/a&gt; use case. My work is influenced by two blog posts from &lt;a href="https://www.jetstack.io/blog/istio-oidc/"&gt;jetstack&lt;/a&gt; and &lt;a href="https://elastisys.com/istio-and-oauth2-proxy-in-kubernetes-for-microservice-authentication/"&gt;elastisys&lt;/a&gt; on similar topic, with my own additions, simplifications and clarifications. In this lab I use my own DNS hostname &lt;span style="text-decoration: underline" class="underline"&gt;demo1.digihunch.com&lt;/span&gt; and to follow along you need to bring your own hostname as well. The prerequisites of this lab is summarized as below:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;An &lt;strong&gt;identity provider&lt;/strong&gt;: we use Google in the lab but it can be anything with OIDC capabilities (e.g. Azure AD, Facebook). Read my &lt;a href="https://static.digihunch.com/2020/03/oauth-and-openid-connect/"&gt;old post&lt;/a&gt; for more details on OIDC.&lt;/li&gt;&#10;&lt;li&gt;A &lt;strong&gt;public IP address&lt;/strong&gt; for Cluster&amp;#8217;s Ingress service: Since we use Google as identity provider on the Internet, we need our service to be exposed on the Internet because the OIDC integration involves a two-way HTTP redirect. &lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Public DNS resolution&lt;/strong&gt; to the service&amp;#8217;s public IP: during authentication, the identity provider will call back with JWT. So we need our hostname demo1.digihunch.com resolved to the service&amp;#8217;s public IP address. This is also required in other scenarios. For example, cert-manager needs to automatically configure X.509 certificate using Let&amp;#8217;s Encrypt.&lt;/li&gt;&#10;&lt;li&gt;An &lt;strong&gt;application workload&lt;/strong&gt;: this is the tenant workload without its own IAM capability. We use a dummy workload base on a &lt;a href="https://hub.docker.com/r/neilpeterson/aks-helloworld"&gt;hello-world&lt;/a&gt; image, for simplicity.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The files required in this lab is in &lt;a href="https://github.com/digihunch/istio-oidc"&gt;istio-oidc&lt;/a&gt; repo under the &lt;a href="https://github.com/digihunch/istio-oidc/tree/main/envoy"&gt;envoy&lt;/a&gt; directory. It is also important to understand the Authentication Code flow in OIDC authorization code flow to make sense of the integration between OIDC provider and Istio on our platform. For example, the client application needs a one-time registration with identity provider. Let&amp;#8217;s start with this configuration.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="configure-identity-provider"&gt;Configure Identity Provider&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We need a Google account with a GCP project and log on to &lt;a href="https://console.cloud.google.com/apis/"&gt;APIs &amp;amp; Services&lt;/a&gt; to register our application. At the console, from the left side bar, click on &amp;#8220;OAuth consent screen&amp;#8221; and create an App. Provide the followings:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Step 1. OAuth consent screen. Under App Information, provide App name and User support email.&lt;/li&gt;&#10;&lt;li&gt;Step 1. OAuth consent screen. Under App domain, provide Application home page&lt;/li&gt;&#10;&lt;li&gt;Step 1. OAuth consent screen. Under Authorized domains, provide an Authorized domain.&lt;/li&gt;&#10;&lt;li&gt;Step 3. Test users. Add the emails for Test users.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The summary page looks like this:&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-large"&gt;&lt;img loading="lazy" decoding="async" width="1012" height="1332" src="https://static.digihunch.com/wp-content/uploads/2022/02/summary.png" alt="" class="wp-image-3607"/&gt;&lt;figcaption class="wp-element-caption"&gt;OAuth Consent Screen&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Then on the sidebar, click on Credentials. We create new credentials for OAuth 2.0 Client ID. Select Web application and add &amp;#8220;https://demo1.digihunch.com/oauth2/callback&amp;#8221; as an Authorized redirect URI. The credential created includes a Client ID and a Client secret, which can be downloaded as a JSON file. Here is my screen:&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-large"&gt;&lt;img loading="lazy" decoding="async" width="1332" height="818" src="https://static.digihunch.com/wp-content/uploads/2022/02/credentials.png" alt="" class="wp-image-3608"/&gt;&lt;figcaption class="wp-element-caption"&gt;API Credential&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that the redirect URIs cannot be localhost. Because the browser will consume the redirect URI and it has no clue where localhost is. It must resolve to the public IP of the ingress.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We need to keep the Client ID and Client secret for later use. According to Google&amp;#8217;s &lt;a href="https://developers.google.com/identity/protocols/oauth2/openid-connect"&gt;documentation&lt;/a&gt;, there is a &lt;a href="https://developers.google.com/identity/protocols/oauth2/openid-connect#discovery"&gt;discovery document&lt;/a&gt; from which we can understand the keys in their &lt;a href="https://accounts.google.com/.well-known/openid-configuration"&gt;Open ID configuration&lt;/a&gt;. We need the value of two keys (&lt;em&gt;issuer&lt;/em&gt; and &lt;em&gt;jwks_url&lt;/em&gt;) to use later in the configuration.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="configure-infrastructure-services"&gt;Configure Infrastructure Services&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;My real-quicK-cluster &lt;a href="https://github.com/digihunch/real-quicK-cluster"&gt;project&lt;/a&gt; has a few different ways to quickly bring up a cluster. For this lab, I use Azure CLI command to create a simple, three-node cluster:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ az aks create &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -g AutomationTest &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -n orthCluster &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --node-count &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --enable-addons monitoring &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --generate-ssh-keys &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --vm-set-type VirtualMachineScaleSets &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --network-plugin azure &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --network-policy calico &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --tags Owner&lt;span style="color:#f92672"&gt;=&lt;/span&gt;MyOwner&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then we configure kubeconfig credential to connect to the cluster, so that &lt;em&gt;kubectl&lt;/em&gt; and &lt;em&gt;helm&lt;/em&gt; CLI commands to connect to the newly created cluster.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ az aks get-credentials --resource-group AutomationTest --name orthCluster&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then we will install the infrastructure services and workload. We can start with loading environment variables for use later:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;OIDC_DISCOVERY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;curl &lt;span style="color:#e6db74"&gt;&amp;#34;https://accounts.google.com/.well-known/openid-configuration&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;OIDC_ISSUER_URL&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;echo $OIDC_DISCOVERY | jq -r .issuer&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;OIDC_JWKS_URI&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;echo $OIDC_DISCOVERY | jq -r .jwks_uri&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;COOKIE_SECRET&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;openssl rand -base64 &lt;span style="color:#ae81ff"&gt;32&lt;/span&gt; | tr -- &lt;span style="color:#e6db74"&gt;&amp;#39;+/&amp;#39;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;-_&amp;#39;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WEB_HOST&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;demo1.digihunch.com&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CLIENT_ID&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThisIsTheClientIDFromGoogle&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CLIENT_SECRET&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;ThisIsTheClientSecretFromGoogle&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;For WEB_HOST, CLIENT_ID, CLIENT_SECRET, you need to bring your own values. The COOKIE_SECRET value is randomly generated. The variables OIDC_ISSUER_URL and OIDC_JWKS_URI are parsed from Google OpenID configuration and they should remain static. We can validate the value with echo commands. Also, to use helm v3 later, we need to add the repositories we need. These steps can be skipped if they have been performed in the client environment:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ echo $OIDC_ISSUER_URL&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;https://accounts.google.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ echo $OIDC_JWKS_URI&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;https://www.googleapis.com/oauth2/v3/certs&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ helm repo add jetstack https://charts.jetstack.io&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ helm repo add istio https://istio-release.storage.googleapis.com/charts&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ helm repo add oauth2-proxy https://oauth2-proxy.github.io/manifests&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ helm repo update&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Now, with Helm ready, we can install Cert Manager, Istio CRD, Control Plane, Gateways as well as OAuth2-Proxy using Helm. We run each of the following commands from the &lt;a href="https://github.com/digihunch/istio-oidc/tree/main/envoy"&gt;envoy&lt;/a&gt; directory, where the required files are stored:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ helm install cert-manager jetstack/cert-manager &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --namespace cert-manager &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --create-namespace &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --version v1.7.1 &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set installCRDs&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ helm install -n istio-system istio-base istio/base --create-namespace&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ helm -n istio-system install istiod istio/istiod -f istiod-values.yaml --wait&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ helm -n istio-system install istio-ingress istio/gateway -f ingress-gateway-values.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kubectl -n istio-system get po&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kubectl create ns oauth2-proxy &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; kubectl label ns oauth2-proxy istio-injection&lt;span style="color:#f92672"&gt;=&lt;/span&gt;enabled&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ helm install -n oauth2-proxy &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --version 6.0.1 &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --values oauth2-proxy-values.yaml &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set config.clientID&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$CLIENT_ID &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set config.clientSecret&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$CLIENT_SECRET &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set config.cookieSecret&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$COOKIE_SECRET &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set extraArgs.oidc-issuer-url&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$OIDC_ISSUER_URL &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set extraArgs.whitelist-domain&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$WEB_HOST &lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; oauth2-proxy oauth2-proxy/oauth2-proxy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kubectl -n oauth2-proxy get pods -l app&lt;span style="color:#f92672"&gt;=&lt;/span&gt;oauth2-proxy&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Note that the istiod installation step uses a value file that includes extensionProviders. This is where we tell Istio to connect to external authorization provider:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;meshConfig&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;accessLogFile&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;/dev/stdout&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;extensionProviders&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;oauth2-proxy&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;envoyExtAuthzHttp&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;service&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;oauth2-proxy.oauth2-proxy.svc.cluster.local&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;4180&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;includeRequestHeadersInCheck&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;cookie&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;headersToUpstreamOnAllow&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;authorization&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;headersToDownstreamOnDeny&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;set-cookie&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;When we install istio ingress gateway, we need to expose port 80 as well as 443. Port 80 is used in ACME protocol for certificate configuration. We also installed oauth2-proxy with some configurations from oauth2-proxy-values.yaml as well as some argument set imperatively.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Once configuration is successful, we should be able to confirm that oauth2-proxy service is running. We should also be able to tell the External IP address of the Ingress:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kubectl -n oauth2-proxy get svc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kubectl -n istio-system get service istio-ingressgateway -o jsonpath&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;{.status.loadBalancer.ingress[0].ip}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Now we can go to our DNS configuration portal, to populate the DNS A-record for demo1.digihunch.com with this IP address:&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-large"&gt;&lt;img loading="lazy" decoding="async" width="1756" height="434" src="https://static.digihunch.com/wp-content/uploads/2022/02/dns.png" alt="" class="wp-image-3620"/&gt;&lt;figcaption class="wp-element-caption"&gt;Add DNS A-record&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;It may take several minutes to a couple of hours, for the A-record update/creation to take effect, depending on the TTL. Sit tight and query DNS with nslookup command, until it is set. In the next step, we will need successful DNS resolution for certificate configuration.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="install-workload-and-configure-certificate"&gt;Install workload and configure Certificate&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Now we install the workload, along with the necessary constructs such as Gateway CRD, Virtual Service, and certificates. We can use kubectl kustomize command to preview the changes, then apply the changes with -k:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kubectl kustomize demo&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kubectl apply -k demo&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;When you have your own DNS hostname, modify the &lt;a href="https://github.com/digihunch/istio-oidc/blob/main/envoy/demo/kustomization.yaml"&gt;kustomization.yaml&lt;/a&gt; accordingly before applying. This command uses Kustomization to apply numerous YAML manifests in the &lt;a href="https://github.com/digihunch/istio-oidc/tree/main/envoy/demo"&gt;demo&lt;/a&gt; directory, including the following activities:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;Create a Namespace named demo&lt;/li&gt;&#10;&lt;li&gt;Create Deployment and Service&lt;/li&gt;&#10;&lt;li&gt;Set up PeerAuthentication for the mesh&lt;/li&gt;&#10;&lt;li&gt;Configure Ingress class, ClusterIssuer and Certificate using cert-manager&lt;/li&gt;&#10;&lt;li&gt;Configure Virtual Service and Gateway&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This configures everything we need and we need to verify from several aspects. The demo Service is a ClusterIP service exposed within the cluster at port 80. Then we check the status of certificate:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kubectl -n istio-system get certificate&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kubectl -n istio-system describe certificate demo&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The column of READY should have a value of True. Check the logs from cert manager Pods if that&amp;#8217;s not the case. Common reasons include:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;The automatic ACME validation is just not ready &lt;/li&gt;&#10;&lt;li&gt;The automatic ACME validation is still waiting for DNS resolution&lt;/li&gt;&#10;&lt;li&gt;The Istio ingress gateway port 80 is not open for ACME validation&lt;/li&gt;&#10;&lt;li&gt;The let&amp;#8217;s encrypt server applies rate limiting&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that for the ACME server, we can use staging server&amp;#8217;s URL or productions. The former provisions a certificate that may come off as insecure as the CA is not fully trusted by browser. The latter doesn&amp;#8217;t have this issue, but the server applies rate limiting. For more details of how validation with ACME work, check out my &lt;a href="https://static.digihunch.com/2021/08/creating-tls-certificate-kubernetes/"&gt;previous post&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Once the certificate is applied, our website is open to any visitor with HTTPS access:&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="748" height="257" src="https://static.digihunch.com/wp-content/uploads/2022/02/image-5.png" alt="" class="wp-image-3636"/&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Then we will use Request Authentication and Authorization Policy to tighten up the access by requiring visiting user to log in with Google identity.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="requestauthentication-and-authorizationpolicy"&gt;RequestAuthentication and AuthorizationPolicy&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We configure a CUSTOM action in the AuthorizationPolicy, and specified the provider by name oauth2-proxy. The YAML manifests for RequestAuthentication and AuthorizationPolicy looks like this:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;security.istio.io/v1beta1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;RequestAuthentication&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio-ingressgateway&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio-system&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;jwtRules&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;issuer&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;https://accounts.google.com&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;jwksUri&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;https://www.googleapis.com/oauth2/v3/certs&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;selector&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;matchLabels&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio-ingressgateway&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;security.istio.io/v1beta1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;AuthorizationPolicy&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio-ingressgateway&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio-system&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;action&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;CUSTOM&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;provider&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;oauth2-proxy&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;rules&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - {}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;selector&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;matchLabels&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio-ingressgateway&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Note that we cannot apply Request Authentication and Authorization Policy before we confirm that the Certificate has been created. This is because when letsencrypt use HTTP resolver to provision certificate with ACME protocol, the request from letsencrypt should get to the validating URI without being asked to provide a Google identity. So do not perform this step yet before confirming the previous step:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;$ kubectl apply -f oidc-auth.yaml&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Now launch your browser in incognito mode and browse to our URL (https://demo1.digihunch.com) and you will be re-redirected to log on to Google (accounts.google.com). Once logged on, you will have access to the site. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If you run into errors, check the oauth2-proxy log from Pod stdout, which should give a reason of 4xx errors. If oauth2-proxy log indicates no activity, confirm if the request has been forwarded to the proxy. Check the service object of the proxy and make sure it is exposed to the correct port, as indicated in the meshConfig. To check mesh config, examine the configmap named istio in the namespace of istio-system. To check if Istio&amp;#8217;s authorization is unable to speak with oatuh2-proxy, inspect the log of istiod Pod.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To clean up the lab, remove the app registration from Google, and then delete the cluster from Azure:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ az aks delete -g AutomationTest -n orthCluster&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;In this lab we used a very open AuthorizationPolicy. We can polish it up with more conditions such as:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;security.istio.io/v1beta1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;AuthorizationPolicy&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio-ingressgateway&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio-system&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;action&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;CUSTOM&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;provider&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;oauth2-proxy&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;rules&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;when&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;key&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;request.auth.audiences&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;values&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;$CLIENT_ID&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;selector&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;matchLabels&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;istio-ingressgateway&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Under the rules section, we can explore the claims from the JWT and make creative use of it to achieve our specific goals for IAM.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="bottom-line"&gt;Bottom line&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In this lab, we registered our app with Google and obtained client ID and secret for it to identify our application. We configured oauth2-proxy as our IAM application, carrying the credential validated by Google. We also configured Istio to delegate authorization to oauth2-proxy as external authorization provide, making up an entire OIDC integration.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The third party service (IdP) we integrate with is GCP, which natively supports OIDC protocol. However, if the third party IdP does not support OIDC natively, such as &lt;a href="https://static.digihunch.com/2020/02/everything-about-the-domain/"&gt;Active Directory&lt;/a&gt; via &lt;a href="https://static.digihunch.com/2020/03/lightweight-directory-access-protocol-ldap/"&gt;LDAP&lt;/a&gt;, then we would need one more proxy to sit between OAuth2 and the external IdP service. One good choice is the &lt;a href="https://www.cncf.io/projects/dex/"&gt;Dex&lt;/a&gt; connector. Another more complex yet powerful alternative connector is &lt;a href="https://www.keycloak.org/"&gt;Key Cloak&lt;/a&gt;. Consider Dex or KeyCloak as an OIDC proxy, when: &lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;The external IdP does not support OIDC; or&lt;/li&gt;&#10;&lt;li&gt;We choose not to use the OIDC capability of the external IdP because we want to managed OIDC centrally in our own proxy&lt;/li&gt;&#10;&lt;li&gt;The external identity provider does support OIDC, but the configuration is managed by a different team (e.g. IAM team) other than the platform team&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;AuthorizationPolicy is the key piece in this integration, and it is executed at the http filter in envoy sidecar proxy. It can be done with alternatives to OAuth2-Proxy such as the &lt;a href="https://github.com/istio-ecosystem/authservice"&gt;authservice&lt;/a&gt; project. A slightly different approach to implement OIDC integration is to use leverage &lt;a href="https://istio.io/latest/blog/2020/wasm-announce/"&gt;extensibility&lt;/a&gt; of &lt;a href="https://istio.io/latest/docs/concepts/wasm/"&gt;WebAssembly&lt;/a&gt; (a sandboxing technology to extend Envoy), which is suggested in this example for &lt;a href="https://istio.io/latest/docs/reference/config/proxy_extensions/wasm-plugin/"&gt;WasmPlugin&lt;/a&gt;. However, Wasm is still considered experimental.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2022/02/istio-lab-authentication-and-authorization-in-jwt/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Istio Lab – Authentication and Authorization&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2022/03/from-nginx-to-envoy-proxy/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Service Proxy – from Nginx to Envoy&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>