<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Open ID Connect on Digi Hunch</title><link>https://www.digihunch.com/tag/open-id-connect/</link><description>Recent content in Open ID Connect on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Wed, 02 Apr 2025 10:41:25 -0400</lastBuildDate><atom:link href="https://www.digihunch.com/tag/open-id-connect/index.xml" rel="self" type="application/rss+xml"/><item><title>Test Open ID Connect Flows Locally</title><link>https://www.digihunch.com/2024/08/test-open-id-connect-flows-locally/</link><pubDate>Mon, 05 Aug 2024 13:24:34 -0400</pubDate><guid>https://www.digihunch.com/2024/08/test-open-id-connect-flows-locally/</guid><description>&lt;img src="https://www.digihunch.com/wp-content/uploads/2025/04/feature-local-oidc-test.webp" alt="Featured image of post Test Open ID Connect Flows Locally" /&gt;&lt;p class="wp-block-paragraph"&gt;Earlier this year, I had to integrate an application with an identity provider. Both claim to be compliant with &lt;a href="https://www.digihunch.com/2023/07/oauth-2-0-and-oidc-2-of-2/"&gt;Open ID Connect&lt;/a&gt;. But when they don&amp;#8217;t get along, I must find out where it breaks to determine which party isn&amp;#8217;t compliant. Therefore, I had to really get to the transaction-level details. As a result, I was eager to find out a way to test Open ID Connect Flows locally. Considering that I discussed OIDC in several past &lt;a href="https://www.digihunch.com/2023/07/oauth-2-0-and-oidc-2-of-2/"&gt;articles&lt;/a&gt; and use cases (&lt;a href="https://www.digihunch.com/2023/07/authenticate-kube-apiserver-via-oidc/"&gt;authenticating to kube-api server&lt;/a&gt;, Kubernetes &lt;a href="https://www.digihunch.com/2023/12/workload-identity-on-kubernetes-1-of-2-aks/"&gt;workload&lt;/a&gt;, &lt;a href="https://www.digihunch.com/2023/06/kubernetes-paas-and-red-hat-openshift/"&gt;ROSA&lt;/a&gt;), I feel it is important to be able to test Open ID Connect flows locally.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Architecture&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;What makes local testing difficult is that there are several parties involved and they act in different roles. Take &lt;a href="https://www.digihunch.com/2023/07/oauth-2-0-and-oidc-2-of-2/"&gt;Authorization Code Flow&lt;/a&gt; as an example, the main actors are:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;User Agent: the browser;&lt;/li&gt;&#10;&lt;li&gt;Authorization Server: an identity store, also referred to as identity provider;&lt;/li&gt;&#10;&lt;li&gt;Resource server: an HTTP server that returns protected resource;&lt;/li&gt;&#10;&lt;li&gt;OIDC client application: the component that communicates with identity store on behalf of the resource server;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Apart from the bowser (obviously running on my laptop), we can group the the other actors in different patterns. Here I illustrate some options below:&lt;/p&gt;&#10;&lt;p class="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="751px" viewBox="-0.5 -0.5 751 731" style="max-width:100%;max-height:731px;"&gt;&lt;defs&gt;&lt;/defs&gt;&lt;g&gt;&lt;g data-cell-id="0"&gt;&lt;g data-cell-id="1"&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-68"&gt;&lt;g&gt;&lt;rect x="0" y="0" width="750" height="730" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-62"&gt;&lt;g&gt;&lt;rect x="370" y="580" width="370" height="110" fill="#f5f5f5" stroke="#666666" stroke-dasharray="3 3" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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 flex-end; width: 368px; height: 1px; padding-top: 587px; margin-left: 370px;"&gt;&lt;div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: right;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Server Pattern&lt;div&gt;Example #4&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="738" y="599" fill="#333333" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="end"&gt;Server Pattern&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-61"&gt;&lt;g&gt;&lt;rect x="370" y="232.5" width="260" height="80" fill="#f5f5f5" stroke="#666666" stroke-dasharray="3 3" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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 flex-end; width: 258px; height: 1px; padding-top: 239px; margin-left: 370px;"&gt;&lt;div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: right;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Server Pattern&lt;div&gt;Example #2&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="628" y="251" fill="#333333" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="end"&gt;Server Pattern&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-58"&gt;&lt;g&gt;&lt;rect x="370" y="80" width="260" height="80" fill="#f5f5f5" stroke="#666666" stroke-dasharray="3 3" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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 flex-end; width: 258px; height: 1px; padding-top: 87px; margin-left: 370px;"&gt;&lt;div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: right;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Server Pattern&lt;div&gt;Example #1&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="628" y="99" fill="#333333" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="end"&gt;Server Pattern&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-48"&gt;&lt;g&gt;&lt;rect x="10" y="490" width="220" height="225" fill="#f5f5f5" stroke="#666666" stroke-dasharray="3 3" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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 flex-start; width: 218px; height: 1px; padding-top: 497px; margin-left: 12px;"&gt;&lt;div data-drawio-colors="color: #333333; " 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(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Client&amp;nbsp;&lt;span style="background-color: initial;"&gt;Pattern Ex.#3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="12" y="509" fill="#333333" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px"&gt;Client&amp;nbsp;Pattern Ex.#3&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-47"&gt;&lt;g&gt;&lt;rect x="10" y="250" width="220" height="220" fill="#f5f5f5" stroke="#666666" stroke-dasharray="3 3" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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 flex-start; width: 218px; height: 1px; padding-top: 257px; margin-left: 12px;"&gt;&lt;div data-drawio-colors="color: #333333; " 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(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Client Pattern&lt;div&gt;Example #2&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="12" y="269" fill="#333333" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px"&gt;Client Pattern&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-46"&gt;&lt;g&gt;&lt;rect x="10" y="60" width="220" height="180" fill="#f5f5f5" stroke="#666666" stroke-dasharray="3 3" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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 flex-start; width: 218px; height: 1px; padding-top: 67px; margin-left: 12px;"&gt;&lt;div data-drawio-colors="color: #333333; " 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(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Client Pattern&lt;div&gt;Example #1&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="12" y="79" fill="#333333" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px"&gt;Client Pattern&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-23"&gt;&lt;g&gt;&lt;rect x="25" y="520" width="200" height="90" rx="13.5" ry="13.5" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 198px; height: 1px; padding-top: 527px; margin-left: 26px;"&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;Advanced Reverse Proxy&lt;div&gt;(e.g. Nginx Plus, Traefik Enterprise)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="125" y="539" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;Advanced Reverse Proxy&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-3"&gt;&lt;g&gt;&lt;rect x="40" y="150" width="180" height="80" rx="12" ry="12" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 178px; height: 1px; padding-top: 157px; margin-left: 41px;"&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;&lt;div&gt;&lt;span style="background-color: initial;"&gt;App (with built-in&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: initial;"&gt;OIDC support)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="130" y="169" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;App (with built-in&amp;nbsp;OIDC suppor&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-4"&gt;&lt;g&gt;&lt;rect x="600" y="620" width="130" height="60" rx="9" ry="9" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 128px; height: 1px; padding-top: 650px; margin-left: 601px;"&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;Identity Provider with&lt;div&gt;OIDC support&amp;nbsp;&lt;/div&gt;&lt;div&gt;(e.g. Active Directory)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="665" y="654" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;Identity Provider wit&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-5"&gt;&lt;g&gt;&lt;path d="M 240 720 L 240 20" fill="none" stroke="rgb(0, 0, 0)" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-6"&gt;&lt;g&gt;&lt;rect x="35" y="10" width="160" height="30" fill="none" stroke="none" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 158px; height: 1px; padding-top: 25px; margin-left: 36px;"&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; font-weight: bold; white-space: normal; overflow-wrap: normal;"&gt;OIDC Client App Patterns&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="115" y="29" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle" font-weight="bold"&gt;OIDC Client App Patterns&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-7"&gt;&lt;g&gt;&lt;rect x="390" y="10" width="220" height="30" fill="none" stroke="none" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 218px; height: 1px; padding-top: 25px; margin-left: 391px;"&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; font-weight: bold; white-space: normal; overflow-wrap: normal;"&gt;OIDC Authorization Server Patterns&lt;div&gt;(including Identity Provider)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="500" y="29" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle" font-weight="bold"&gt;OIDC Authorization Server Patterns&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-8"&gt;&lt;g&gt;&lt;path d="M 360 720 L 360 20" fill="none" stroke="rgb(0, 0, 0)" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-9"&gt;&lt;g&gt;&lt;ellipse cx="85" cy="200" rx="35" ry="25" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/ellipse&gt;&lt;/g&gt;&lt;g&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: 68px; height: 1px; padding-top: 200px; margin-left: 51px;"&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;HTTP&lt;div&gt;Resource&lt;/div&gt;&lt;div&gt;&lt;span style="background-color: initial;"&gt;Server&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="85" y="204" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;HTTP&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-15"&gt;&lt;g&gt;&lt;ellipse cx="135" cy="345" rx="50" ry="15" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/ellipse&gt;&lt;/g&gt;&lt;g&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: 98px; height: 1px; padding-top: 345px; margin-left: 86px;"&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="135" y="349" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;oauth2-proxy&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-16"&gt;&lt;g&gt;&lt;rect x="380" y="90" width="160" height="60" rx="9" ry="9" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 158px; height: 1px; padding-top: 120px; margin-left: 381px;"&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;Self-hosted OIDC-capable&lt;div&gt;Identity Providers&lt;/div&gt;&lt;div&gt;(e.g. KeyCloak as IdP)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="460" y="124" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;Self-hosted OIDC-capable&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-17"&gt;&lt;g&gt;&lt;rect x="50" y="380" width="170" height="80" rx="12" ry="12" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 168px; height: 1px; padding-top: 387px; margin-left: 51px;"&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;&lt;div&gt;&lt;span style="background-color: initial;"&gt;App (without&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: initial;"&gt;OIDC capability)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="135" y="399" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;App (without&amp;nbsp;OIDC capability)&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-18"&gt;&lt;g&gt;&lt;ellipse cx="175" cy="200" rx="35" ry="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/ellipse&gt;&lt;/g&gt;&lt;g&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: 68px; height: 1px; padding-top: 200px; margin-left: 141px;"&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;OIDC&lt;div&gt;library&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="175" y="204" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;OIDC&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-20"&gt;&lt;g&gt;&lt;ellipse cx="82.5" cy="580" rx="47.5" ry="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/ellipse&gt;&lt;/g&gt;&lt;g&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: 93px; height: 1px; padding-top: 580px; margin-left: 36px;"&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;reverse&amp;nbsp;&lt;span style="background-color: initial;"&gt;proxy&lt;/span&gt;&lt;div&gt;capability&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="83" y="584" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;reverse&amp;nbsp;proxy&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-24"&gt;&lt;g&gt;&lt;ellipse cx="175" cy="580" rx="40" ry="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/ellipse&gt;&lt;/g&gt;&lt;g&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: 580px; margin-left: 136px;"&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;oidc client&lt;div&gt;capability&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="175" y="584" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;oidc client&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-27"&gt;&lt;g&gt;&lt;rect x="380" y="242.5" width="160" height="60" rx="9" ry="9" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 158px; height: 1px; padding-top: 272px; margin-left: 381px;"&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;&lt;div&gt;Commercial OIDC-capable&lt;/div&gt;Identity Providers&lt;div&gt;(e.g. MS Entra-ID, Google)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="460" y="276" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;Commercial OIDC-capableIde&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-35"&gt;&lt;g&gt;&lt;rect x="85" y="90" width="90" height="45" rx="6.75" ry="6.75" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 113px; margin-left: 86px;"&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;(optional)&lt;div&gt;reverse proxy&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="130" y="116" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;(optional)&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-36"&gt;&lt;g&gt;&lt;ellipse cx="135" cy="425" rx="35" ry="25" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/ellipse&gt;&lt;/g&gt;&lt;g&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: 68px; height: 1px; padding-top: 425px; margin-left: 101px;"&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;HTTP&lt;div&gt;Resource&lt;/div&gt;&lt;div&gt;&lt;span style="background-color: initial;"&gt;Server&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="135" y="429" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;HTTP&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-37"&gt;&lt;g&gt;&lt;rect x="90" y="275" width="90" height="37.5" rx="5.63" ry="5.63" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 294px; margin-left: 91px;"&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;(optional)&lt;div&gt;reverse proxy&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="135" y="297" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;(optional)&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-38"&gt;&lt;g&gt;&lt;rect x="25" y="630" width="200" height="80" rx="12" ry="12" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 198px; height: 1px; padding-top: 637px; margin-left: 26px;"&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;&lt;div&gt;&lt;span style="background-color: initial;"&gt;App (without&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: initial;"&gt;OIDC capability)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="125" y="649" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;App (without&amp;nbsp;OIDC capability)&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-39"&gt;&lt;g&gt;&lt;ellipse cx="125" cy="680" rx="35" ry="25" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/ellipse&gt;&lt;/g&gt;&lt;g&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: 68px; height: 1px; padding-top: 680px; margin-left: 91px;"&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;HTTP&lt;div&gt;Resource&lt;/div&gt;&lt;div&gt;&lt;span style="background-color: initial;"&gt;Server&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="125" y="684" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;HTTP&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-40"&gt;&lt;g&gt;&lt;path d="M 135 312.5 L 135 323.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 135 328.88 L 131.5 321.88 L 135 323.63 L 138.5 321.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-41"&gt;&lt;g&gt;&lt;path d="M 135 373.63 L 135 360" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 135 378.88 L 131.5 371.88 L 135 373.63 L 138.5 371.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-42"&gt;&lt;g&gt;&lt;path d="M 130 143.63 L 130 135" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 130 148.88 L 126.5 141.88 L 130 143.63 L 133.5 141.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-50"&gt;&lt;g&gt;&lt;path d="M 125 623.63 L 125 610" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 125 628.88 L 121.5 621.88 L 125 623.63 L 128.5 621.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-52"&gt;&lt;g&gt;&lt;path d="M 130 70 L 130 83.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 130 88.88 L 126.5 81.88 L 130 83.63 L 133.5 81.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-54"&gt;&lt;g&gt;&lt;path d="M 124.73 500 L 124.73 513.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 124.73 518.88 L 121.23 511.88 L 124.73 513.63 L 128.23 511.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-55"&gt;&lt;g&gt;&lt;path d="M 135 255 L 135 268.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 135 273.88 L 131.5 266.88 L 135 268.63 L 138.5 266.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-57"&gt;&lt;g&gt;&lt;rect x="380" y="620" width="120" height="60" rx="9" ry="9" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 118px; height: 1px; padding-top: 650px; margin-left: 381px;"&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;&lt;div&gt;Any OIDC-capable&lt;/div&gt;Identity Broker&amp;nbsp;&lt;div&gt;&lt;span style="background-color: initial;"&gt;e.g. Dex&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="440" y="654" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;Any OIDC-capableIden&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-59"&gt;&lt;g&gt;&lt;path d="M 519.45 654.19 L 519.34 664.69 L 500.5 649 L 519.65 633.7 L 519.55 644.2 L 580.55 644.81 L 580.66 634.31 L 599.5 650 L 580.35 665.3 L 580.45 654.8 Z" fill="#fff2cc" stroke="#d6b656" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-60"&gt;&lt;g&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: 1px; height: 1px; padding-top: 621px; margin-left: 551px;"&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: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"&gt;Other Protocol&lt;div&gt;(e.g. LDAP, SAML)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="551" y="624" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="11px" text-anchor="middle"&gt;Other Protocol&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-34"&gt;&lt;g&gt;&lt;path d="M 275 380 C 255 380 250 400 266 404 C 250 412.8 268 432 281 424 C 290 440 320 440 330 424 C 350 424 350 408 337.5 400 C 350 384 330 368 312.5 376 C 300 364 280 364 275 380 Z" fill="#d5e8d4" stroke="#82b366" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g&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: 98px; height: 1px; padding-top: 400px; margin-left: 251px;"&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;Standard&lt;div&gt;OIDC Flow&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="300" y="404" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;Standard&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-63"&gt;&lt;g&gt;&lt;rect x="370" y="390" width="370" height="110" fill="#f5f5f5" stroke="#666666" stroke-dasharray="3 3" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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 flex-end; width: 368px; height: 1px; padding-top: 397px; margin-left: 370px;"&gt;&lt;div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: right;"&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"&gt;Server Pattern&lt;div&gt;Example #3&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="738" y="409" fill="#333333" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="end"&gt;Server Pattern&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-64"&gt;&lt;g&gt;&lt;rect x="600" y="430" width="130" height="60" rx="9" ry="9" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 128px; height: 1px; padding-top: 460px; margin-left: 601px;"&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;Identity Provider with&lt;div&gt;OIDC support&amp;nbsp;&lt;/div&gt;&lt;div&gt;(e.g. Active Directory)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="665" y="464" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;Identity Provider wit&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-65"&gt;&lt;g&gt;&lt;rect x="380" y="430" width="120" height="60" rx="9" ry="9" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 118px; height: 1px; padding-top: 460px; margin-left: 381px;"&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;&lt;div&gt;KeyCloak as&lt;/div&gt;&lt;div&gt;Identity Broker&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="440" y="464" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;KeyCloak as&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-66"&gt;&lt;g&gt;&lt;path d="M 519.45 464.19 L 519.34 474.69 L 500.5 459 L 519.65 443.7 L 519.55 454.2 L 580.55 454.81 L 580.66 444.31 L 599.5 460 L 580.35 475.3 L 580.45 464.8 Z" fill="#fff2cc" stroke="#d6b656" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g data-cell-id="MkZjjGYqzHr3rgLKbynL-67"&gt;&lt;g&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: 1px; height: 1px; padding-top: 426px; margin-left: 551px;"&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: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"&gt;Other Protocol&lt;div&gt;(e.g. LDAP, SAML)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="551" y="429" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="11px" text-anchor="middle"&gt;Other Protocol&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&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.drawio.com/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"&gt;In essence, we need an OIDC client app and an authorization server. And I find the most simplistic test architecture to be pattern #2 (without reverse proxy) on the client side, and pattern #1 on the server side. In the next section let&amp;#8217;s discuss why I prefer this test architecture.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Choice of Tools&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The principle of this lab is that we can focus on the OIDC flows itself and simplify every other aspects as much as we can.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The authorization server needs to access my client app. As a result, if I use a public authorization server, such as Azure or Google, I&amp;#8217;d have to host my client app on a public IP with domain name as well. This creates churns. To see how much hassle this can involve, review my article &lt;a href="https://www.digihunch.com/2022/02/istio-external-authorization/"&gt;Istio External Authentication lab&lt;/a&gt;. Instead, I need a tool to host the authorization server on my laptop. And yes, it&amp;#8217;s &lt;a href="https://www.keycloak.org/"&gt;KeyCloak&lt;/a&gt;. It is a well-renewed open-source project for identity and access management. It is also the upstream project of &lt;a href="https://access.redhat.com/products/red-hat-single-sign-on"&gt;RedHat SSO&lt;/a&gt;. Another reason is it operates on PostgreSQL database which is a common relational database technology with release in Docker images.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the client side, we can have our web service with built-in OIDC capability, which usually requires development work in a language with OIDC library. Alternatively, if the client app lacks such capability, we would address this capability in a different component on the client side. It can either be a standalone, purpose-built proxy, or a generic reverse proxy with OIDC capability. For this, I examined a few options. &lt;a href="https://github.com/nginxinc/nginx-openid-connect"&gt;Nginx&lt;/a&gt; and &lt;a href="https://doc.traefik.io/traefik-enterprise/middlewares/oidc/"&gt;Traefik&lt;/a&gt; have OIDC support for a fee in their Enterprise product. Apache has a module &lt;a href="https://github.com/OpenIDC/mod_auth_openidc"&gt;mod_auth_oidc&lt;/a&gt; for free but it requires building the plug-in on my own for Mac platform. Eventually I landed on the purpose-built option, using the &lt;a href="https://github.com/oauth2-proxy/oauth2-proxy"&gt;oauth2-proxy&lt;/a&gt; open source project. This project can act as both actor #3 (with a minimal HTTP server) and actor #4 (OIDC client). So it also saves me from hosting a separate web server. Also, I have used it in the past in the &lt;a href="https://www.digihunch.com/2022/02/istio-external-authorization/"&gt;Istio External Authentication lab&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In reality, each message in the OIDC flows must be TLS encrypted. In local testing though we don&amp;#8217;t really care. Similarly we don&amp;#8217;t necessary need a reverse proxy if it plays no role in the OIDC flow. Both Keycloak (with PostgreSQL) and oauth2-proxy are released in Docker images. As a result, we are ready to roll with only three tools: the browser on local host, Keycloak and oauth2-proxy in the Docker daemon, which provides great portability.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To get started, let&amp;#8217;s have two fictitious domains, &lt;code&gt;web.digihunch.com&lt;/code&gt;, and &lt;code&gt;keycloak.digihunch.com&lt;/code&gt;. In the Docker compose manifest, I name the services based on their hostname so that they can reference each other from within the container network namespace. To access the service from the host, I force the DNS resolution to localhost in &lt;code&gt;/etc/hosts&lt;/code&gt; on my Mac, and make sure to declare the same host port in the port mapping (4180 for dummy web service; and 8080 for Keycloak).&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Configuration&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I created a Docker compose file as below, to set up my test:&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;services&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;web.digihunch.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;container_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;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;quay.io/oauth2-proxy/oauth2-proxy:latest&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;command&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;http-address&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;0.0.0.0&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;environment&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;OAUTH2_PROXY_COOKIE_SECRET&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;NYZaClZinINKwxNGzEDeFGh64W6tmq1eB6uHQPa4S5o &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;OAUTH2_PROXY_CLIENT_ID&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;dh-user-client&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;OAUTH2_PROXY_CLIENT_SECRET&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;pmkwBjkVesrj7fw1MY7h5s9e3cmAKXgc &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;OAUTH2_PROXY_PROVIDER&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;oidc &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;OAUTH2_PROXY_OIDC_ISSUER_URL&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;http://keycloak.digihunch.com:8080/realms/digihunch-users&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;OAUTH2_PROXY_PASS_ACCESS_TOKEN&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&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;OAUTH2_PROXY_EMAIL_DOMAINS&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;*&amp;#39;&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;OAUTH2_PROXY_REDIRECT_URL&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;http://web.digihunch.com:4180/oauth2/callback&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;OAUTH2_PROXY_PROVIDER_DISPLAY_NAME&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;DHCKC&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;OAUTH2_PROXY_COOKIE_CSRF_EXPIRE&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;5m&amp;#39;&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;OAUTH2_PROXY_COOKIE_CSRF_PER_REQUEST&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&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;OAUTH2_PROXY_COOKIE_SECURE&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Needed for HTTP connection&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:#75715e"&gt;#OAUTH2_PROXY_UPSTREAMS: file:///var/www/static/#/home/ # serve page at /home path&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;OAUTH2_PROXY_UPSTREAMS&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;static://202 &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;volumes&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;./config/oauth2-proxy.cfg:/etc/oauth2-proxy.cfg&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# - ./config/www:/var/www/static/&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;ports&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;4180&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;networks&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;oidc_network&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;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;unless-stopped&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;depends_on&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;keycloak.digihunch.com&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;postgres-db&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;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;postgres&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;container_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;postgresdb&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;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&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;shm_size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;128mb&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;ports&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;5432&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;5432&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;networks&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;oidc_network&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;volumes&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;./data/pgdata:/var/lib/postgresql/data&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;environment&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;POSTGRES_USER=master&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;POSTGRES_PASSWORD=masterpass&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;POSTGRES_DB=keycloak&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;keycloak.digihunch.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;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;quay.io/keycloak/keycloak&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;command&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;start&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;environment&lt;/span&gt;: &lt;span style="color:#75715e"&gt;# Based on Hostname:v2 https://www.keycloak.org/docs/25.0.0/upgrading/#migrating-to-25-0-0&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;KC_HOSTNAME&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;http://keycloak.digihunch.com:8080&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#KC_HOSTNAME_ADMIN: For simplicity, no separate management URL or port&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;KC_HOSTNAME_BACKCHANNEL_DYNAMIC&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&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;KC_HTTP_ENABLED&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; &lt;span style="color:#75715e"&gt;## Otherwise HTTPS is the enforced by default.&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;KC_HEALTH_ENABLED&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&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;KEYCLOAK_ADMIN&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;admin &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;KEYCLOAK_ADMIN_PASSWORD&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;kcadminpass&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;KC_DB&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;postgres&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;KC_DB_URL&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;jdbc:postgresql://postgres-db/keycloak&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;KC_DB_USERNAME&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;master&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;KC_DB_PASSWORD&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;masterpass &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;ports&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;8080&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;8080&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;networks&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;oidc_network&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;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&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;depends_on&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;postgres-db&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;networks&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;oidc_network&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;enable_ipv6&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&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;driver&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;bridge&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 OAuth2-Proxy, the &lt;a href="https://quay.io/repository/oauth2-proxy/oauth2-proxy"&gt;official image&lt;/a&gt; for oauth2-proxy is distroless. So if you have to troubleshoot its container file system, you need to access it via an &lt;a href="https://medium.com/@ananthsekar007/troubleshooting-strategies-for-distroless-containers-unveiling-solutions-in-minimalist-ca2e284b6e1a"&gt;assistant container&lt;/a&gt;:&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-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run --rm -it --name debugger --privileged --pid container:oauth2-proxy --network container:oauth2-proxy busybox sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# to see target container&amp;#39;s file system, go to: ls -l /proc/1/root/&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Alternatively, we can use the one that Bitnami &lt;a href="https://hub.docker.com/r/bitnami/oauth2-proxy/tags"&gt;releases&lt;/a&gt; but be vary of some &lt;a href="https://github.com/oauth2-proxy/oauth2-proxy/issues/1802#issuecomment-1447999568"&gt;nuances&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the Keycloak part, I use environment variables and had to watch out for the recent changes on &lt;a href="https://www.keycloak.org/docs/25.0.0/upgrading/#migrating-to-25-0-0"&gt;hostname v2&lt;/a&gt;. We should first start up the Keycloak service. From http://keycloak.digihunch.com:8080, we can login using the credential specified in the environment variables, then we can create a client app: &lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;Create a new realm (dropdown-&amp;gt; Create realm) with name digihunch-users&lt;/li&gt;&#10;&lt;li&gt;Switch to this realm from the dropdown, create a couple users (e.g. dhadmin@www.digihunch.com), and set password.&lt;/li&gt;&#10;&lt;li&gt;Create a group (e.g. myadmin) and join the user to the group&lt;/li&gt;&#10;&lt;li&gt;Under the same realm, create a client, with OpenID Connect as type, client ID being dh-user-client. turn on client authentication (without Direct access grants)&lt;/li&gt;&#10;&lt;li&gt;Save the client for now and grab the client secret. Note that the OIDC discovery document (http://keycloak.digihunch.com:8080/realms/digihunch-users/.well-known/openid-configuration) should come online.&lt;/li&gt;&#10;&lt;li&gt;Update the docker compose file:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;The value for OAUTH2_PROXY_CLIENT_SECRET is from the client secret; &lt;/li&gt;&#10;&lt;li&gt;The value for OAUTH2_PROXY_OIDC_ISSUER_URL should be http://keycloak.digihunch.com:8080/realms/digihunch-users; &lt;/li&gt;&#10;&lt;li&gt;The value for OAUTH2_PROXY_CLIENT_ID is dh-user-client;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Restart all services including the web. Log on to keycloak and go back to the client configuration in the realm. Under settings. Put in valid redirect URIs as http://web.digihunch.com:4180/oauth2/callback and save the client. &lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Now, let&amp;#8217;s start an private browser session, and browse to http://web.digihunch.com:4180/. The browser should redirect you to keycloak&amp;#8217;s login page. Once log in is successful, it should redirect you to the static response with 202 code as the manifest configured.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Summary&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In this post, I laid out the steps to test the login for OIDC authorization code flow locally as a starting point. For a bullet-proof solution, I recommend taking a look at KeyCloak &lt;a href="https://www.keycloak.org/docs/latest/server_admin/"&gt;administration guide&lt;/a&gt;. For example, we typically disable the master realm for security. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There is a similar test setup on &lt;a href="https://developer.okta.com/blog/2022/07/14/add-auth-to-any-app-with-oauth2-proxy"&gt;Otka blog&lt;/a&gt; but I simplified all the aspects that I regard as distractors. There are many other flows that can be tested. However, some of the testing still requires client pattern #1 if we need to initiates an activity from the client application.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://www.digihunch.com/2024/07/iam-roles-for-any-workload/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;IAM Roles for any workload&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://www.digihunch.com/2024/08/debating-between-count-and-for_each-in-terraform/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Debating between count and for_each in Terraform&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>IAM Roles for any workload</title><link>https://www.digihunch.com/2024/07/iam-roles-for-any-workload/</link><pubDate>Sun, 14 Jul 2024 23:53:49 -0400</pubDate><guid>https://www.digihunch.com/2024/07/iam-roles-for-any-workload/</guid><description>&lt;img src="https://www.digihunch.com/wp-content/uploads/2025/04/feature-iam-role-anywhere.webp" alt="Featured image of post IAM Roles for any workload" /&gt;&lt;h2 class="wp-block-heading"&gt;Background&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A few month back a client of mine wanted to use GitLab pipeline to deploy infrastructure on AWS with Terraform. The key question is how to authenticate the Terraform process running in the pipeline to AWS with temporary credential. Having &lt;a href="https://www.digihunch.com/2023/01/github-action-gotchas/"&gt;worked it out on GitHub&lt;/a&gt;, my proposal at time was to &lt;a href="https://docs.gitlab.com/ee/ci/cloud_services/aws/"&gt;add OIDC provider&lt;/a&gt; to represent the GitLab runner. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;After a few months, they told me that they are self-hosting their GitLab instance. The idea above was based on exposing an identity provider document on the public Internet, which the client is unable to do. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Now, I have an idea: IAM Roles Anywhere.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;IAM Role Introduction&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Many 101 tutorials asks beginners to create standalone IAM users (or group) with IAM policies directly attached. For programatic access they also include creating a pair of access key and secret access key and pass them along to an external application. The keys are long term credentials, and worse, never expires. The leakage of these long-term credentials had been such a headache that AWS strongly discourage the use of long term credentials. You can feel the discouragement when trying to create an access key through the web console, or by the banners on top of the &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html"&gt;documentation page&lt;/a&gt; about how to do so. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The recommendation is use temporary security credentials. In the context of AWS that means IAM roles. The users must assume an IAM role by issuing an API call, and the Security Token Service (STS) grants temporary credential in response.&lt;/p&gt;&#10;&lt;p class="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="351px" viewBox="-0.5 -0.5 351 122" style="max-width:100%;max-height:122px;"&gt;&lt;defs&gt;&lt;/defs&gt;&lt;g&gt;&lt;g data-cell-id="0"&gt;&lt;g data-cell-id="1"&gt;&lt;g data-cell-id="VRZMaZhQ_cbes_kdLvWi-8"&gt;&lt;g&gt;&lt;rect x="0" y="0" width="350" height="120" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="VRZMaZhQ_cbes_kdLvWi-1"&gt;&lt;g&gt;&lt;path d="M 320 76.55 C 320 78.52 318.4 80 316.39 80 L 275.69 80 C 273.24 80 272 78.23 272 76.73 L 272 23.42 C 272 21.21 273.91 20 275.64 20 L 316.61 20 C 318.37 20 320 21.41 320 23.36 Z" fill="#759c3e" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 295.89 56.07 C 287 56.07 278.95 49.27 278.95 39.5 C 278.95 30.98 286.32 23.48 296.19 23.48 C 304.93 23.48 313.05 30.44 313.05 39.71 C 313.05 48.35 305.84 56.07 295.89 56.07 Z" fill="#4f4f4f" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 290.59 67.19 L 289.18 67.19 C 289.18 66.44 288.94 65.57 287.89 65.1 C 287.29 64.88 286.32 64.7 285.21 65.03 C 284.66 65.21 284.16 65.6 284.03 66.33 C 283.83 67.41 284.66 67.82 285.47 68.06 C 287.2 68.52 287.94 68.57 288.78 68.88 C 289.71 69.2 290.7 69.74 291 70.92 C 291.25 72.24 290.73 73.18 290.02 73.74 C 289.29 74.34 288.02 74.8 286.34 74.74 C 284.99 74.68 283.8 74.23 283.11 73.54 C 282.51 72.94 282.12 72.18 282.12 71.01 L 283.51 71.01 C 283.56 72.22 284.17 72.91 285.07 73.32 C 286.09 73.71 287.44 73.72 288.38 73.32 C 288.99 73.06 289.55 72.54 289.54 71.68 C 289.52 70.86 288.97 70.36 287.76 70.05 C 286.65 69.75 285.55 69.68 284.52 69.32 C 283.44 68.93 282.23 68.21 282.53 66.33 C 282.71 65.16 283.64 64.33 285.11 63.98 C 286.46 63.7 287.91 63.83 288.89 64.34 C 289.87 64.87 290.54 65.81 290.59 67.19 Z M 300.45 65.04 L 296.82 65.04 L 296.82 74.38 L 295.34 74.38 L 295.34 65.04 L 291.64 65.04 L 291.64 63.82 L 300.45 63.82 Z M 309.41 67.19 L 308 67.19 C 308 66.44 307.76 65.55 306.71 65.07 C 306.12 64.85 305.15 64.67 304.03 65.01 C 303.48 65.19 302.98 65.57 302.85 66.3 C 302.65 67.4 303.48 67.8 304.3 68.04 C 306.02 68.51 306.75 68.54 307.61 68.85 C 308.53 69.17 309.52 69.71 309.8 70.89 C 310.07 72.22 309.55 73.15 308.85 73.72 C 308.11 74.31 306.84 74.77 305.16 74.71 C 303.81 74.67 302.62 74.2 301.93 73.51 C 301.33 72.93 300.94 72.18 300.94 71.01 L 302.34 71.01 C 302.38 72.22 303 72.88 303.89 73.29 C 304.91 73.69 306.26 73.71 307.2 73.3 C 307.81 73.05 308.38 72.52 308.36 71.65 C 308.35 70.84 307.78 70.35 306.59 70.03 C 305.47 69.72 304.38 69.65 303.34 69.29 C 302.26 68.91 301.05 68.18 301.35 66.32 C 301.54 65.13 302.46 64.31 303.94 63.95 C 305.29 63.67 306.73 63.82 307.7 64.33 C 308.69 64.85 309.36 65.81 309.41 67.19 Z M 298.93 42.57 L 298.93 29.55 L 295.42 29.55 L 295.42 39.21 L 288.94 39.21 L 288.94 42.57 Z M 295.95 52.7 C 288.61 52.7 282.46 46.9 282.46 39.65 C 282.46 32.29 288.96 26.83 296.13 26.83 C 303.15 26.83 309.52 32.51 309.52 39.77 C 309.52 47.09 303.15 52.7 295.95 52.7 Z" fill="#ffffff" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="VRZMaZhQ_cbes_kdLvWi-2"&gt;&lt;g&gt;&lt;path d="M 56.16 79.58 L 48.37 75.17 L 43 78.24 L 30 70.84 L 30 56.08 L 37.43 51.83 L 37.43 32.71 L 59.71 20 L 82 32.69 L 82 58.05 L 64.07 68.25 L 64.07 75.04 Z" fill="#444444" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 59.71 44.44 L 79.65 33.11 L 59.79 21.87 L 39.94 33.11 Z M 42.35 63.72 L 31.21 57.4 L 31.21 70.11 L 42.35 76.5 Z M 42.92 62.75 L 54.06 56.35 L 42.92 50.03 L 31.78 56.35 Z M 54.7 62.3 L 54.7 57.48 L 43.56 63.79 L 43.56 76.5 L 48.17 73.87 L 48.17 65.98 Z M 58.9 63.12 L 58.9 45.9 L 39.04 34.57 L 39.04 50.92 L 42.99 48.66 L 55.91 56.02 L 55.91 61.62 L 56.08 61.54 Z M 64.06 66.51 L 80.46 57.16 L 80.46 34.49 L 60.6 45.82 L 60.6 64.07 L 64.06 66.03 Z M 55.92 69.87 L 62.05 66.39 L 55.99 62.9 L 49.93 66.39 Z M 55.51 77.8 L 55.51 70.84 L 49.37 67.35 L 49.37 74.32 Z M 56.63 77.8 L 62.78 74.32 L 62.78 67.35 L 56.63 70.84 Z" fill="#ffffff" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g&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: 87px; margin-left: 56px;"&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;CLI&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="56" y="99" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;CLI&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="VRZMaZhQ_cbes_kdLvWi-4"&gt;&lt;g&gt;&lt;path d="M 82 32.81 L 263.63 32.99" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 268.88 33 L 261.88 36.49 L 263.63 32.99 L 261.89 29.49 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g data-cell-id="VRZMaZhQ_cbes_kdLvWi-6"&gt;&lt;g&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: 1px; height: 1px; padding-top: 20px; margin-left: 163px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;Request: AssumeRole*&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="163" y="23" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="11px" text-anchor="middle"&gt;Request: AssumeRole*&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="VRZMaZhQ_cbes_kdLvWi-5"&gt;&lt;g&gt;&lt;path d="M 270 60 L 88.37 57.91" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 83.12 57.85 L 90.16 54.43 L 88.37 57.91 L 90.08 61.43 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g data-cell-id="VRZMaZhQ_cbes_kdLvWi-7"&gt;&lt;g&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: 90px; margin-left: 122px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: left;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;Response:&lt;div&gt;&amp;#8211; AccessKeyId&lt;/div&gt;&lt;div&gt;&amp;#8211; SecretAccessKey&lt;/div&gt;&lt;div&gt;&amp;#8211; SessionToken&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="122" y="94" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="11px"&gt;Response:&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&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.drawio.com/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"&gt;This diagram has several variations. For example, the request can be AssumeRole, AssumeRoleWithSAML and AssumeRoleWithWebIdentity, depending on whether and how the user info is federated with external identity store. The returned response, a triplet of three values, makes the temporary credential that we should use in any secure environment. They must be renewed before expiry. This model works not only for human identity (e.g. SAML integration, OIDC integration, cross-account access) but also for workload identity (e.g. EC2 instance profile, Lambda execution role, ECS task role, etc). &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Another good example is &lt;a href="https://www.digihunch.com/2024/01/workload-identity-on-kubernetes-2-of-2-eks-and-rosa-on-aws/"&gt;IAM Role for Service Account (IRSA)&lt;/a&gt;, where a web identity represents a Kuberentes Service Account to gain role credential using the AssumeRoleWithWebIdentity API. In this post however, I&amp;#8217;d like to explore more about the IAM role for EC2 instance profile.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;The IMDS service &lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For EC2 instance, we all know that we can associate an IAM role as the instance profile and grant the process using AWS SDK running on the instance with permissions associated with the IAM role. At a lower level, this relies on the IMDS (Instance Metadata Service) running on the instance.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If an EC2 instance&amp;#8217;s profile points to an IAM role, a process running on the instance using AWS SDK will also need to get the triplet from the STS. It is summarized in this diagram:&lt;/p&gt;&#10;&lt;p class="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="531px" viewBox="-0.5 -0.5 531 141" style="max-width:100%;max-height:141px;"&gt;&lt;defs&gt;&lt;/defs&gt;&lt;g&gt;&lt;g data-cell-id="0"&gt;&lt;g data-cell-id="1"&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-1"&gt;&lt;g&gt;&lt;rect x="0" y="0" width="530" height="140" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-2"&gt;&lt;g&gt;&lt;rect x="10" y="10" width="330" height="100" fill="#d5e8d4" stroke="#82b366" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-3"&gt;&lt;g&gt;&lt;path d="M 518 101.55 C 518 103.52 516.4 105 514.39 105 L 473.69 105 C 471.24 105 470 103.23 470 101.73 L 470 48.42 C 470 46.21 471.91 45 473.64 45 L 514.61 45 C 516.37 45 518 46.41 518 48.36 Z" fill="#759c3e" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 493.89 81.07 C 485 81.07 476.95 74.27 476.95 64.5 C 476.95 55.98 484.32 48.48 494.19 48.48 C 502.93 48.48 511.05 55.44 511.05 64.71 C 511.05 73.35 503.84 81.07 493.89 81.07 Z" fill="#4f4f4f" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 488.59 92.19 L 487.18 92.19 C 487.18 91.44 486.94 90.57 485.89 90.1 C 485.29 89.88 484.32 89.7 483.21 90.03 C 482.66 90.21 482.16 90.6 482.03 91.33 C 481.83 92.41 482.66 92.82 483.47 93.06 C 485.2 93.52 485.94 93.57 486.78 93.88 C 487.71 94.2 488.7 94.74 489 95.92 C 489.25 97.24 488.73 98.18 488.02 98.74 C 487.29 99.34 486.02 99.8 484.34 99.74 C 482.99 99.68 481.8 99.23 481.11 98.54 C 480.51 97.94 480.12 97.18 480.12 96.01 L 481.51 96.01 C 481.56 97.22 482.17 97.91 483.07 98.32 C 484.09 98.71 485.44 98.72 486.38 98.32 C 486.99 98.06 487.55 97.54 487.54 96.68 C 487.52 95.86 486.97 95.36 485.76 95.05 C 484.65 94.75 483.55 94.68 482.52 94.32 C 481.44 93.93 480.23 93.21 480.53 91.33 C 480.71 90.16 481.64 89.33 483.11 88.98 C 484.46 88.7 485.91 88.83 486.89 89.34 C 487.87 89.87 488.54 90.81 488.59 92.19 Z M 498.45 90.04 L 494.82 90.04 L 494.82 99.38 L 493.34 99.38 L 493.34 90.04 L 489.64 90.04 L 489.64 88.82 L 498.45 88.82 Z M 507.41 92.19 L 506 92.19 C 506 91.44 505.76 90.55 504.71 90.07 C 504.12 89.85 503.15 89.67 502.03 90.01 C 501.48 90.19 500.98 90.57 500.85 91.3 C 500.65 92.4 501.48 92.8 502.3 93.04 C 504.02 93.51 504.75 93.54 505.61 93.85 C 506.53 94.17 507.52 94.71 507.8 95.89 C 508.07 97.22 507.55 98.15 506.85 98.72 C 506.11 99.31 504.84 99.77 503.16 99.71 C 501.81 99.67 500.62 99.2 499.93 98.51 C 499.33 97.93 498.94 97.18 498.94 96.01 L 500.34 96.01 C 500.38 97.22 501 97.88 501.89 98.29 C 502.91 98.69 504.26 98.71 505.2 98.3 C 505.81 98.05 506.38 97.52 506.36 96.65 C 506.35 95.84 505.78 95.35 504.59 95.03 C 503.47 94.72 502.38 94.65 501.34 94.29 C 500.26 93.91 499.05 93.18 499.35 91.32 C 499.54 90.13 500.46 89.31 501.94 88.95 C 503.29 88.67 504.73 88.82 505.7 89.33 C 506.69 89.85 507.36 90.81 507.41 92.19 Z M 496.93 67.57 L 496.93 54.55 L 493.42 54.55 L 493.42 64.21 L 486.94 64.21 L 486.94 67.57 Z M 493.95 77.7 C 486.61 77.7 480.46 71.9 480.46 64.65 C 480.46 57.29 486.96 51.83 494.13 51.83 C 501.15 51.83 507.52 57.51 507.52 64.77 C 507.52 72.09 501.15 77.7 493.95 77.7 Z" fill="#ffffff" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-4"&gt;&lt;g&gt;&lt;rect x="212.5" y="60" width="105" height="35" rx="5.25" ry="5.25" fill="#ffe6cc" stroke="#d79b00" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 103px; height: 1px; padding-top: 78px; margin-left: 214px;"&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;IMDS v2&lt;div&gt;169.254.169.254&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="265" y="81" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;IMDS v2&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-5"&gt;&lt;g&gt;&lt;rect x="30" y="62.5" width="120" height="30" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 118px; height: 1px; padding-top: 78px; margin-left: 31px;"&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;AWS SDK&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="90" y="81" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;AWS SDK&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-6"&gt;&lt;g&gt;&lt;path d="M 149.88 74.26 L 206.76 75.35" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 212.01 75.45 L 204.95 78.81 L 206.76 75.35 L 205.08 71.82 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-7"&gt;&lt;g&gt;&lt;path d="M 211.87 84.5 L 156.37 84.95" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 151.12 84.99 L 158.09 81.43 L 156.37 84.95 L 158.15 88.43 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-8"&gt;&lt;g&gt;&lt;path d="M 317.29 70.78 L 463.63 70.03" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 468.88 70.01 L 461.9 73.54 L 463.63 70.03 L 461.86 66.54 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-9"&gt;&lt;g&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: 1px; height: 1px; padding-top: 58px; margin-left: 398px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;Request: AssumeRole&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="398" y="61" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="11px" text-anchor="middle"&gt;Request: AssumeRole&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-10"&gt;&lt;g&gt;&lt;path d="M 470 80 L 322.29 81.53" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 317.04 81.58 L 324.01 78.01 L 322.29 81.53 L 324.08 85.01 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-11"&gt;&lt;g&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: 112px; margin-left: 352px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: left;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;Response:&lt;div&gt;&amp;#8211; AccessKeyId&lt;/div&gt;&lt;div&gt;&amp;#8211; SecretAccessKey&lt;/div&gt;&lt;div&gt;&amp;#8211; SessionToken&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="352" y="115" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="11px"&gt;Response:&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-12"&gt;&lt;g&gt;&lt;rect x="30" y="25" width="120" height="37.5" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;path d="M 42 25 L 42 62.5 M 138 25 L 138 62.5" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g&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: 94px; height: 1px; padding-top: 44px; margin-left: 43px;"&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;Application&lt;div&gt;Process&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="90" y="47" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;Application&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="mtzehsWG86ey03g9Zuuk-13"&gt;&lt;g&gt;&lt;path d="M 180 20 L 210 20 L 210 50 L 180 50 Z" fill="#ed7100" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 189.43 40.57 L 200.14 40.57 L 200.14 29.86 L 189.43 29.86 Z M 201 29.86 L 202.71 29.86 L 202.71 30.71 L 201 30.71 L 201 32.43 L 202.71 32.43 L 202.71 33.29 L 201 33.29 L 201 34.57 L 202.71 34.57 L 202.71 35.43 L 201 35.43 L 201 37.14 L 202.71 37.14 L 202.71 38 L 201 38 L 201 39.71 L 202.71 39.71 L 202.71 40.57 L 201 40.57 L 201 40.63 C 201 41.07 200.64 41.43 200.2 41.43 L 200.14 41.43 L 200.14 43.14 L 199.29 43.14 L 199.29 41.43 L 197.57 41.43 L 197.57 43.14 L 196.71 43.14 L 196.71 41.43 L 195.43 41.43 L 195.43 43.14 L 194.57 43.14 L 194.57 41.43 L 192.86 41.43 L 192.86 43.14 L 192 43.14 L 192 41.43 L 190.29 41.43 L 190.29 43.14 L 189.43 43.14 L 189.43 41.43 L 189.37 41.43 C 188.93 41.43 188.57 41.07 188.57 40.63 L 188.57 40.57 L 187.29 40.57 L 187.29 39.71 L 188.57 39.71 L 188.57 38 L 187.29 38 L 187.29 37.14 L 188.57 37.14 L 188.57 35.43 L 187.29 35.43 L 187.29 34.57 L 188.57 34.57 L 188.57 33.29 L 187.29 33.29 L 187.29 32.43 L 188.57 32.43 L 188.57 30.71 L 187.29 30.71 L 187.29 29.86 L 188.57 29.86 L 188.57 29.8 C 188.57 29.36 188.93 29 189.37 29 L 189.43 29 L 189.43 27.29 L 190.29 27.29 L 190.29 29 L 192 29 L 192 27.29 L 192.86 27.29 L 192.86 29 L 194.57 29 L 194.57 27.29 L 195.43 27.29 L 195.43 29 L 196.71 29 L 196.71 27.29 L 197.57 27.29 L 197.57 29 L 199.29 29 L 199.29 27.29 L 200.14 27.29 L 200.14 29 L 200.2 29 C 200.64 29 201 29.36 201 29.8 Z M 195.43 46.09 C 195.43 46.12 195.4 46.14 195.38 46.14 L 183.91 46.14 C 183.88 46.14 183.86 46.12 183.86 46.09 L 183.86 34.62 C 183.86 34.6 183.88 34.57 183.91 34.57 L 186.43 34.57 L 186.43 33.71 L 183.91 33.71 C 183.41 33.71 183 34.12 183 34.62 L 183 46.09 C 183 46.59 183.41 47 183.91 47 L 195.38 47 C 195.88 47 196.29 46.59 196.29 46.09 L 196.29 44 L 195.43 44 Z M 207 23.91 L 207 35.38 C 207 35.88 206.59 36.29 206.09 36.29 L 203.57 36.29 L 203.57 35.43 L 206.09 35.43 C 206.12 35.43 206.14 35.4 206.14 35.38 L 206.14 23.91 C 206.14 23.88 206.12 23.86 206.09 23.86 L 194.62 23.86 C 194.6 23.86 194.57 23.88 194.57 23.91 L 194.57 26.43 L 193.71 26.43 L 193.71 23.91 C 193.71 23.41 194.12 23 194.62 23 L 206.09 23 C 206.59 23 207 23.41 207 23.91 Z" fill="#ffffff" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g&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: 35px; margin-left: 212px;"&gt;&lt;div data-drawio-colors="color: #232F3E; " 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(35, 47, 62); line-height: 1.2; pointer-events: all; white-space: nowrap;"&gt;&lt;div&gt;&lt;span style="background-color: initial;"&gt;EC2 Instance&lt;/span&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="212" y="39" fill="#232F3E" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px"&gt;EC2 I&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&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.drawio.com/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"&gt;The IMDS is a service available on one of the link-local IP address (169.254.169.254) on the EC2 instance. Requests made to this IP address are not routed elsewhere. The Instance Metadata Service (IMDS) is a means for the cloud service provider&amp;#8217;s virtualization layer to share information with the processes on the operating system of a virtual machine. It responds with information related to the instance itself, such as the subnets, IAM role, instance ID, AMI ID, security group. The instance metadata also includes user data script for cloud init process to consume, and most relevantly, the role credential for the instance. This also requires that the IMDS service to have connectivity to the STS endpoint, either via interface endpoint or over the Internet. The AssumeRole calls are logged in CloudTrail.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;All major cloud vendors (AWS, Azure and GCP) uses the IMDS mechanism, and this mechanism obviously draws the attention of bad actors. I find some good articles on this &lt;a href="https://www.sans.org/blog/cloud-instance-metadata-services-imds-/"&gt;here&lt;/a&gt; and &lt;a href="https://www.tenable.com/blog/secure-your-aws-ec2-instance-metadata-service-imds"&gt;here&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;IAM Role for EC2 Workload&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For EC2 instances at AWS, the initial IMDS v1 was introduced in 2012 and allows a GET method to fetch instance metadata. The IMDS v1 is subject to attacks such as SSRF (Server-side request forgery). In 2019 AWS introduced IMDS v2 which tackles those &lt;a href="https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/"&gt;vulnerabilities&lt;/a&gt;. As of date, the recommendation is to use IMDSv2. Here is an example of how to fetch instance metadata, including the credential:&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;&lt;span style="color:#75715e"&gt;# Grab a token&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TOKEN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;curl -X PUT &lt;span style="color:#e6db74"&gt;&amp;#34;http://169.254.169.254/latest/api/token&amp;#34;&lt;/span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-aws-ec2-metadata-token-ttl-seconds: 21600&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Get top-level instance metadata information&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl http://169.254.169.254/latest/meta-data/profile -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-aws-ec2-metadata-token: &lt;/span&gt;$TOKEN&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Get the name of the role&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-aws-ec2-metadata-token: &lt;/span&gt;$TOKEN&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; http://169.254.169.254/latest/meta-data/iam/security-credentials&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Get the credential for the role session&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-aws-ec2-metadata-token: &lt;/span&gt;$TOKEN&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; http://169.254.169.254/latest/meta-data/iam/security-credentials/InstanceProfileRoleName&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;These commands emulate how the SDK library fetches the credentials to assume the instance profile role. You can also find similar commands on the &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#instance-metadata-security-credentials"&gt;documentation&lt;/a&gt;. However, there isn&amp;#8217;t much details about how the instance metadata service interacts with the STS service, except a general statement:&lt;/p&gt;&#10;&lt;blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;/p&gt;&#10;&lt;cite&gt;These security credentials are temporary and we rotate them automatically. We make new credentials available at least five minutes before the expiration of the old credentials.&lt;/cite&gt;&lt;/blockquote&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When creating a new EC2 instance, make sure that the instance metadata option has http_endpoint enabled, to enable the IMDS service. Also set http_tokens to required, which would run IMDSv2 exclusively. With that setup, the application does not have to mana to use an &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/use-a-supported-sdk-version-for-imdsv2.html"&gt;SDK version&lt;/a&gt; that supports IMDSv2. Another metadata option is http_put_response_hop_limit, with default of 1. This limits the number of hops in the metadata request. If the process runs from a Docker container with bridge networking mode, set it to 2 or the process cannot even secure a token.&lt;/p&gt;&#10;&lt;p class="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="581px" viewBox="-0.5 -0.5 581 161" style="max-width:100%;max-height:161px;"&gt;&lt;defs&gt;&lt;/defs&gt;&lt;g&gt;&lt;g data-cell-id="0"&gt;&lt;g data-cell-id="1"&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-1"&gt;&lt;g&gt;&lt;rect x="0" y="0" width="580" height="160" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-2"&gt;&lt;g&gt;&lt;rect x="10" y="10" width="360" height="138.75" fill="#d5e8d4" stroke="#82b366" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-14"&gt;&lt;g&gt;&lt;rect x="20" y="20" width="190" height="110" rx="16.5" ry="16.5" fill="#fff2cc" stroke="#d6b656" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-3"&gt;&lt;g&gt;&lt;path d="M 565.5 114.05 C 565.5 116.02 563.9 117.5 561.89 117.5 L 521.19 117.5 C 518.74 117.5 517.5 115.73 517.5 114.23 L 517.5 60.92 C 517.5 58.71 519.41 57.5 521.14 57.5 L 562.11 57.5 C 563.87 57.5 565.5 58.91 565.5 60.86 Z" fill="#759c3e" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 541.39 93.57 C 532.5 93.57 524.45 86.77 524.45 77 C 524.45 68.48 531.82 60.98 541.69 60.98 C 550.43 60.98 558.55 67.94 558.55 77.21 C 558.55 85.85 551.34 93.57 541.39 93.57 Z" fill="#4f4f4f" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 536.09 104.69 L 534.68 104.69 C 534.68 103.94 534.44 103.07 533.39 102.6 C 532.79 102.38 531.82 102.2 530.71 102.53 C 530.16 102.71 529.66 103.1 529.53 103.83 C 529.33 104.91 530.16 105.32 530.97 105.56 C 532.7 106.02 533.44 106.07 534.28 106.38 C 535.21 106.7 536.2 107.24 536.5 108.42 C 536.75 109.74 536.23 110.68 535.52 111.24 C 534.79 111.84 533.52 112.3 531.84 112.24 C 530.49 112.18 529.3 111.73 528.61 111.04 C 528.01 110.44 527.62 109.68 527.62 108.51 L 529.01 108.51 C 529.06 109.72 529.67 110.41 530.57 110.82 C 531.59 111.21 532.94 111.22 533.88 110.82 C 534.49 110.56 535.05 110.04 535.04 109.18 C 535.02 108.36 534.47 107.86 533.26 107.55 C 532.15 107.25 531.05 107.18 530.02 106.82 C 528.94 106.43 527.73 105.71 528.03 103.83 C 528.21 102.66 529.14 101.83 530.61 101.48 C 531.96 101.2 533.41 101.33 534.39 101.84 C 535.37 102.37 536.04 103.31 536.09 104.69 Z M 545.95 102.54 L 542.32 102.54 L 542.32 111.88 L 540.84 111.88 L 540.84 102.54 L 537.14 102.54 L 537.14 101.32 L 545.95 101.32 Z M 554.91 104.69 L 553.5 104.69 C 553.5 103.94 553.26 103.05 552.21 102.57 C 551.62 102.35 550.65 102.17 549.53 102.51 C 548.98 102.69 548.48 103.07 548.35 103.8 C 548.15 104.9 548.98 105.3 549.8 105.54 C 551.52 106.01 552.25 106.04 553.11 106.35 C 554.03 106.67 555.02 107.21 555.3 108.39 C 555.57 109.72 555.05 110.65 554.35 111.22 C 553.61 111.81 552.34 112.27 550.66 112.21 C 549.31 112.17 548.12 111.7 547.43 111.01 C 546.83 110.43 546.44 109.68 546.44 108.51 L 547.84 108.51 C 547.88 109.72 548.5 110.38 549.39 110.79 C 550.41 111.19 551.76 111.21 552.7 110.8 C 553.31 110.55 553.88 110.02 553.86 109.15 C 553.85 108.34 553.28 107.85 552.09 107.53 C 550.97 107.22 549.88 107.15 548.84 106.79 C 547.76 106.41 546.55 105.68 546.85 103.82 C 547.04 102.63 547.96 101.81 549.44 101.45 C 550.79 101.17 552.23 101.32 553.2 101.83 C 554.19 102.35 554.86 103.31 554.91 104.69 Z M 544.43 80.07 L 544.43 67.05 L 540.92 67.05 L 540.92 76.71 L 534.44 76.71 L 534.44 80.07 Z M 541.45 90.2 C 534.11 90.2 527.96 84.4 527.96 77.15 C 527.96 69.79 534.46 64.33 541.63 64.33 C 548.65 64.33 555.02 70.01 555.02 77.27 C 555.02 84.59 548.65 90.2 541.45 90.2 Z" fill="#ffffff" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-4"&gt;&lt;g&gt;&lt;rect x="260" y="72.5" width="105" height="35" rx="5.25" ry="5.25" fill="#ffe6cc" stroke="#d79b00" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 103px; height: 1px; padding-top: 90px; margin-left: 261px;"&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;IMDS v2&lt;div&gt;169.254.169.254&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="313" y="94" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;IMDS v2&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-5"&gt;&lt;g&gt;&lt;rect x="30" y="87.5" width="120" height="30" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 118px; height: 1px; padding-top: 103px; margin-left: 31px;"&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;AWS SDK&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="90" y="106" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;AWS SDK&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-8"&gt;&lt;g&gt;&lt;path d="M 364.79 83.28 L 511.13 82.53" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 516.38 82.51 L 509.4 86.04 L 511.13 82.53 L 509.36 79.04 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-9"&gt;&lt;g&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: 1px; height: 1px; padding-top: 71px; margin-left: 445px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;Request: AssumeRole&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="445" y="74" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="11px" text-anchor="middle"&gt;Request: AssumeRole&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-10"&gt;&lt;g&gt;&lt;path d="M 517.5 92.5 L 369.79 94.03" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 364.54 94.08 L 371.51 90.51 L 369.79 94.03 L 371.58 97.51 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-11"&gt;&lt;g&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: 124px; margin-left: 400px;"&gt;&lt;div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: left;"&gt;&lt;div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"&gt;Response:&lt;div&gt;&amp;#8211; AccessKeyId&lt;/div&gt;&lt;div&gt;&amp;#8211; SecretAccessKey&lt;/div&gt;&lt;div&gt;&amp;#8211; SessionToken&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="400" y="128" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="11px"&gt;Response:&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-12"&gt;&lt;g&gt;&lt;rect x="30" y="50" width="120" height="37.5" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;path d="M 42 50 L 42 87.5 M 138 50 L 138 87.5" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g&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: 94px; height: 1px; padding-top: 69px; margin-left: 43px;"&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;Application&lt;div&gt;Process&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="90" y="72" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;Application&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-13"&gt;&lt;g&gt;&lt;path d="M 240 20 L 270 20 L 270 50 L 240 50 Z" fill="#ed7100" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 249.43 40.57 L 260.14 40.57 L 260.14 29.86 L 249.43 29.86 Z M 261 29.86 L 262.71 29.86 L 262.71 30.71 L 261 30.71 L 261 32.43 L 262.71 32.43 L 262.71 33.29 L 261 33.29 L 261 34.57 L 262.71 34.57 L 262.71 35.43 L 261 35.43 L 261 37.14 L 262.71 37.14 L 262.71 38 L 261 38 L 261 39.71 L 262.71 39.71 L 262.71 40.57 L 261 40.57 L 261 40.63 C 261 41.07 260.64 41.43 260.2 41.43 L 260.14 41.43 L 260.14 43.14 L 259.29 43.14 L 259.29 41.43 L 257.57 41.43 L 257.57 43.14 L 256.71 43.14 L 256.71 41.43 L 255.43 41.43 L 255.43 43.14 L 254.57 43.14 L 254.57 41.43 L 252.86 41.43 L 252.86 43.14 L 252 43.14 L 252 41.43 L 250.29 41.43 L 250.29 43.14 L 249.43 43.14 L 249.43 41.43 L 249.37 41.43 C 248.93 41.43 248.57 41.07 248.57 40.63 L 248.57 40.57 L 247.29 40.57 L 247.29 39.71 L 248.57 39.71 L 248.57 38 L 247.29 38 L 247.29 37.14 L 248.57 37.14 L 248.57 35.43 L 247.29 35.43 L 247.29 34.57 L 248.57 34.57 L 248.57 33.29 L 247.29 33.29 L 247.29 32.43 L 248.57 32.43 L 248.57 30.71 L 247.29 30.71 L 247.29 29.86 L 248.57 29.86 L 248.57 29.8 C 248.57 29.36 248.93 29 249.37 29 L 249.43 29 L 249.43 27.29 L 250.29 27.29 L 250.29 29 L 252 29 L 252 27.29 L 252.86 27.29 L 252.86 29 L 254.57 29 L 254.57 27.29 L 255.43 27.29 L 255.43 29 L 256.71 29 L 256.71 27.29 L 257.57 27.29 L 257.57 29 L 259.29 29 L 259.29 27.29 L 260.14 27.29 L 260.14 29 L 260.2 29 C 260.64 29 261 29.36 261 29.8 Z M 255.43 46.09 C 255.43 46.12 255.4 46.14 255.38 46.14 L 243.91 46.14 C 243.88 46.14 243.86 46.12 243.86 46.09 L 243.86 34.62 C 243.86 34.6 243.88 34.57 243.91 34.57 L 246.43 34.57 L 246.43 33.71 L 243.91 33.71 C 243.41 33.71 243 34.12 243 34.62 L 243 46.09 C 243 46.59 243.41 47 243.91 47 L 255.38 47 C 255.88 47 256.29 46.59 256.29 46.09 L 256.29 44 L 255.43 44 Z M 267 23.91 L 267 35.38 C 267 35.88 266.59 36.29 266.09 36.29 L 263.57 36.29 L 263.57 35.43 L 266.09 35.43 C 266.12 35.43 266.14 35.4 266.14 35.38 L 266.14 23.91 C 266.14 23.88 266.12 23.86 266.09 23.86 L 254.62 23.86 C 254.6 23.86 254.57 23.88 254.57 23.91 L 254.57 26.43 L 253.71 26.43 L 253.71 23.91 C 253.71 23.41 254.12 23 254.62 23 L 266.09 23 C 266.59 23 267 23.41 267 23.91 Z" fill="#ffffff" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;g&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: 35px; margin-left: 272px;"&gt;&lt;div data-drawio-colors="color: #232F3E; " 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(35, 47, 62); line-height: 1.2; pointer-events: all; white-space: nowrap;"&gt;&lt;div&gt;&lt;span style="background-color: initial;"&gt;EC2 Instance&lt;/span&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="272" y="39" fill="#232F3E" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px"&gt;EC2 I&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-23"&gt;&lt;g&gt;&lt;path d="M 150 110 Q 160 170 171.64 113.74" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 172.7 108.59 L 174.71 116.16 L 171.64 113.74 L 167.86 114.74 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-24"&gt;&lt;g&gt;&lt;path d="M 238.45 107.5 Q 260 170 287.49 105.85" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 289.56 101.03 L 290.02 108.84 L 287.49 105.85 L 283.59 106.08 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-26"&gt;&lt;g&gt;&lt;rect x="180" y="87.5" width="50" height="22.5" fill="#75dfff" stroke="rgb(0, 0, 0)" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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-end; justify-content: unsafe center; width: 48px; height: 1px; padding-top: 85px; margin-left: 181px;"&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;Bridge&lt;div&gt;Network&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="205" y="85" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;Bridge&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-22"&gt;&lt;g&gt;&lt;rect x="220" y="87.5" width="30" height="20" fill="none" stroke="none" pointer-events="all"&gt;&lt;/rect&gt;&lt;path d="M 225.13 105.54 L 225.13 100.05 L 235.79 100.05 L 235.79 102.79 L 241.32 102.79 L 241.32 103.58 L 247.24 103.58 L 247.24 101.23 L 241.32 101.23 L 241.32 102.01 L 236.58 102.01 L 236.58 98.09 L 244.08 98.09 L 244.08 98.87 L 248.82 98.87 L 248.82 96.52 L 244.08 96.52 L 244.08 97.3 L 235.79 97.3 L 235.79 99.26 L 225.13 99.26 L 225.13 96.13 L 232.63 96.13 L 232.63 93.38 L 236.58 93.38 L 236.58 94.56 L 242.5 94.56 L 242.5 91.42 L 236.58 91.42 L 236.58 92.6 L 231.84 92.6 L 231.84 95.34 L 225.13 95.34 L 225.13 89.85 L 250 89.85 L 250 105.54 L 239.74 105.54 L 239.74 107.5 L 238.95 107.5 L 238.95 105.54 L 238.16 105.54 L 238.16 107.5 L 237.37 107.5 L 237.37 105.54 L 236.58 105.54 L 236.58 107.5 L 235.79 107.5 L 235.79 105.54 L 235 105.54 L 235 107.5 L 234.21 107.5 L 234.21 105.54 L 233.42 105.54 L 233.42 107.5 L 232.63 107.5 L 232.63 105.54 L 231.84 105.54 L 231.84 107.5 L 231.05 107.5 L 231.05 105.54 L 230.26 105.54 L 230.26 107.5 L 229.47 107.5 L 229.47 105.54 L 228.68 105.54 L 228.68 107.5 L 227.89 107.5 L 227.89 105.54 Z M 222.76 107.5 L 222.76 88.68 L 220 88.68 L 220 87.5 L 223.95 87.5 L 223.95 107.5 Z" fill="#505050" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-16"&gt;&lt;g&gt;&lt;rect x="160" y="87.5" width="30" height="20" fill="none" stroke="none" pointer-events="all"&gt;&lt;/rect&gt;&lt;path d="M 165.13 105.54 L 165.13 100.05 L 175.79 100.05 L 175.79 102.79 L 181.32 102.79 L 181.32 103.58 L 187.24 103.58 L 187.24 101.23 L 181.32 101.23 L 181.32 102.01 L 176.58 102.01 L 176.58 98.09 L 184.08 98.09 L 184.08 98.87 L 188.82 98.87 L 188.82 96.52 L 184.08 96.52 L 184.08 97.3 L 175.79 97.3 L 175.79 99.26 L 165.13 99.26 L 165.13 96.13 L 172.63 96.13 L 172.63 93.38 L 176.58 93.38 L 176.58 94.56 L 182.5 94.56 L 182.5 91.42 L 176.58 91.42 L 176.58 92.6 L 171.84 92.6 L 171.84 95.34 L 165.13 95.34 L 165.13 89.85 L 190 89.85 L 190 105.54 L 179.74 105.54 L 179.74 107.5 L 178.95 107.5 L 178.95 105.54 L 178.16 105.54 L 178.16 107.5 L 177.37 107.5 L 177.37 105.54 L 176.58 105.54 L 176.58 107.5 L 175.79 107.5 L 175.79 105.54 L 175 105.54 L 175 107.5 L 174.21 107.5 L 174.21 105.54 L 173.42 105.54 L 173.42 107.5 L 172.63 107.5 L 172.63 105.54 L 171.84 105.54 L 171.84 107.5 L 171.05 107.5 L 171.05 105.54 L 170.26 105.54 L 170.26 107.5 L 169.47 107.5 L 169.47 105.54 L 168.68 105.54 L 168.68 107.5 L 167.89 107.5 L 167.89 105.54 Z M 162.76 107.5 L 162.76 88.68 L 160 88.68 L 160 87.5 L 163.95 87.5 L 163.95 107.5 Z" fill="#505050" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-cell-id="rtsicqcqSDVIAgyO7OKc-28"&gt;&lt;g&gt;&lt;rect x="30" y="20" width="110" height="30" fill="none" stroke="none" pointer-events="all"&gt;&lt;/rect&gt;&lt;/g&gt;&lt;g&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: 108px; height: 1px; padding-top: 35px; margin-left: 31px;"&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;Docker Daemon&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="85" y="39" fill="rgb(0, 0, 0)" font-family="&amp;quot;Helvetica&amp;quot;" font-size="12px" text-anchor="middle"&gt;Docker Daemon&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&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.drawio.com/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"&gt;The diagram above illustrates this scenario with two hops.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;IAM Role Anywhere Concept&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As this point, we know that the process of workload assuming an IAM role, is essentially using SDK to gain role credentials from instance metadata. In addition to using SDK and instance metadata, AWS also supports using X.509 certificate to gain role credentials. As a result, workload no longer needs AWS SDK, and it doesn&amp;#8217;t rely on instance metadata from an EC2 instance. This mechanism is known as IAM Role Anywhere, and it greatly expands the use cases for IAM Role. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To make this work, we first have to provide a certificate authority (CA) to AWS as a trust anchor. It can be any X.509 CA including AWS Private CA. The IAM Roles Anywhere will allow any end-entity endorsed by this trust anchor, to assume an IAM role as specified. We also need to create a profile, in which we can add IAM policies directly, or link to an IAM roles with a trust policy for service principal &lt;code&gt;rolesanywhere.amazonaws.com&lt;/code&gt;. &lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="691" height="283" src="https://www.digihunch.com/wp-content/uploads/2024/07/iam-role-anywhere-diagram.webp" alt="" class="wp-image-12989" srcset="https://www.digihunch.com/wp-content/uploads/2024/07/iam-role-anywhere-diagram.webp 691w, https://www.digihunch.com/wp-content/uploads/2024/07/iam-role-anywhere-diagram-300x123.webp 300w" sizes="auto, (max-width: 691px) 100vw, 691px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To gain role credential, the requestor must provide both the private key, and its end-entity certificate. The certificate proofs the endorsement of the CA as Role&amp;#8217;s trust anchor specifies. The private key proofs the requestor&amp;#8217;s identity. The requestor uses the &lt;a href="https://docs.aws.amazon.com/rolesanywhere/latest/userguide/credential-helper.html"&gt;aws_signing_helper&lt;/a&gt; utility to request role credentials. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The utility is compatible with the &lt;code&gt;credential_process&lt;/code&gt; feature in AWS config, which passes the returned role credentials to the AWS config profile for AWS CLI or SDK running on external virtual machine.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;IAM Role Anywhere Lab&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Let&amp;#8217;s tweak the three commands from this &lt;a href="https://www.digihunch.com/2021/08/creating-tls-certificate-kubernetes/"&gt;old post&lt;/a&gt; of mine to create the test materials: a self-signed CA and a certificate signed by the CA:&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;openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days &lt;span style="color:#ae81ff"&gt;356&lt;/span&gt; -nodes -subj &lt;span style="color:#e6db74"&gt;&amp;#39;/CN=Health Certificate Authority&amp;#39;&lt;/span&gt; -addext basicConstraints&lt;span style="color:#f92672"&gt;=&lt;/span&gt;critical,CA:TRUE,pathlen:1 -addext keyUsage&lt;span style="color:#f92672"&gt;=&lt;/span&gt;keyCertSign&#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;cat &amp;gt; ext.cnf &lt;span style="color:#e6db74"&gt;&amp;lt;&amp;lt;EOF&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;[v3_leaf]&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;keyUsage = digitalSignature&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;basicConstraints=CA:false&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;EOF&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;openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj &lt;span style="color:#e6db74"&gt;&amp;#39;/CN=*.digihunch.com&amp;#39;&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;openssl x509 -req -sha256 -days &lt;span style="color:#ae81ff"&gt;365&lt;/span&gt; -in server.csr -CA ca.crt -CAkey ca.key -set_serial &lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; -out server.crt -extfile ext.cnf -extensions v3_leaf&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;I tweak them to add the &lt;a href="https://www.digihunch.com/2024/02/public-key-infrastructure-1-of-3-basics/"&gt;X.509 extensions&lt;/a&gt; to meet the &lt;a href="https://docs.aws.amazon.com/rolesanywhere/latest/userguide/trust-model.html"&gt;requirement&lt;/a&gt; for signature validation. We need the following files from the output.&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;ca.crt -&amp;gt; the certificate of the CA. We provide this file as the trust anchor&lt;/li&gt;&#10;&lt;li&gt;server.crt -&amp;gt; the certificate of the server, we need it as the end-entity certificate&lt;/li&gt;&#10;&lt;li&gt;server.key -&amp;gt; we need to present this file to proof identity of the requestor&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;First, we go to AWS console and create a new trust anchor. Copy the content of ca.crt as the certificate. Then we can create a profile with an IAM role, with the trust policy looking like &lt;a href="https://docs.aws.amazon.com/rolesanywhere/latest/userguide/trust-model.html"&gt;this&lt;/a&gt; example. Then we can request the role credential with one command:&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-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aws_signing_helper credential-process --certificate server.crt --private-key server.key --trust-anchor-arn $TRUST_ANCHOR_ARN --profile-arn $PROFILE_ARN --role-arn $ROLE_ARN&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Moreover, if the workload supports AWS SDK or can use CLI but not an EC2 instance, we can bake this in the AWS profile on the external machine:&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-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[profile myprofile]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;output = json&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;credential_process = aws_signing_helper credential-process --certificate /path/server.crt --private-key /path/server.key --trust-anchor-arn $TRUST_ANCHOR_ARN --profile-arn $PROFILE_ARN --role-arn $ROLE_ARN&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;We can even configure this in any &lt;a href="https://aws.amazon.com/blogs/security/enable-external-pipeline-deployments-to-aws-cloud-by-using-iam-roles-anywhere/"&gt;pipeline&lt;/a&gt; as code to allow deployment from a non-AWS pipeline. &lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Summary&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In summary, apart from native AWS services, an IAM role can trust the following types of principals:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Native IAM identity such as an IAM user or an IAM group&lt;/li&gt;&#10;&lt;li&gt;Authenticated identity from SAML identity provider that IAM is configured to trust&lt;/li&gt;&#10;&lt;li&gt;Authenticated identity from OIDC identity provider that IAM is configured to trust&lt;/li&gt;&#10;&lt;li&gt;Validated identity endorsed by a Certificate Authority that IAM designate as a trust anchor&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The first type is rarely used because few organizations uses AWS IAM as their identity store. Most organizations have their identity store with federation capability via SAML. On the other hand, a lot of modern applications adopts identity stores with OIDC compliance. Now with IAM Role Anywhere, any entity with X.509 identity can also assume an IAM role. It works with any CI/CD pipeline, whether it is self-hosted. Also, it is now more important to keep the keys safe. &lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://www.digihunch.com/2024/05/managing-ec2-instances-across-aws-accounts-ssm/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Managing EC2 instances across accounts with Ansible&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://www.digihunch.com/2024/08/test-open-id-connect-flows-locally/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Test Open ID Connect Flows Locally&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>