diff --git a/dev/docs/concepts/index.xml b/dev/docs/concepts/index.xml index fa0640759..55f7c0c49 100644 --- a/dev/docs/concepts/index.xml +++ b/dev/docs/concepts/index.xml @@ -1,4 +1,4 @@ -Concepts on Heimdallhttps://dadrus.github.io/docs/concepts/Recent content in Concepts on HeimdallHugoen-usMon, 17 Feb 2025 11:36:59 +0000Pipelineshttps://dadrus.github.io/docs/concepts/pipelines/Tue, 29 Nov 2022 22:29:36 +0200https://dadrus.github.io/docs/concepts/pipelines/<div class="sect1"> +Concepts on Heimdallhttps://dadrus.github.io/docs/concepts/Recent content in Concepts on HeimdallHugoen-usTue, 18 Feb 2025 15:31:53 +0000Pipelineshttps://dadrus.github.io/docs/concepts/pipelines/Tue, 29 Nov 2022 22:29:36 +0200https://dadrus.github.io/docs/concepts/pipelines/<div class="sect1"> <h2 id="_overview">Overview</h2> <div class="sectionbody"> <div class="paragraph"> diff --git a/dev/docs/configuration/index.xml b/dev/docs/configuration/index.xml index 9216b6754..8bd395994 100644 --- a/dev/docs/configuration/index.xml +++ b/dev/docs/configuration/index.xml @@ -1,4 +1,4 @@ -Configuration Reference on Heimdallhttps://dadrus.github.io/docs/configuration/Recent content in Configuration Reference on HeimdallHugoen-usMon, 17 Feb 2025 11:36:59 +0000Type Definitionshttps://dadrus.github.io/docs/configuration/types/Thu, 09 Jun 2022 18:56:56 +0200https://dadrus.github.io/docs/configuration/types/<div class="sect1"> +Configuration Reference on Heimdallhttps://dadrus.github.io/docs/configuration/Recent content in Configuration Reference on HeimdallHugoen-usTue, 18 Feb 2025 15:31:53 +0000Type Definitionshttps://dadrus.github.io/docs/configuration/types/Thu, 09 Jun 2022 18:56:56 +0200https://dadrus.github.io/docs/configuration/types/<div class="sect1"> <h2 id="_assertions">Assertions</h2> <div class="sectionbody"> <div class="paragraph"> diff --git a/dev/docs/getting_started/index.xml b/dev/docs/getting_started/index.xml index f7961c521..2b6b71feb 100644 --- a/dev/docs/getting_started/index.xml +++ b/dev/docs/getting_started/index.xml @@ -1,4 +1,4 @@ -Getting Started on Heimdallhttps://dadrus.github.io/docs/getting_started/Recent content in Getting Started on HeimdallHugoen-usMon, 17 Feb 2025 11:36:59 +0000Discover heimdallhttps://dadrus.github.io/docs/getting_started/discover_heimdall/Wed, 29 Nov 2023 22:03:28 +0200https://dadrus.github.io/docs/getting_started/discover_heimdall/<div class="sect1"> +Getting Started on Heimdallhttps://dadrus.github.io/docs/getting_started/Recent content in Getting Started on HeimdallHugoen-usTue, 18 Feb 2025 15:31:53 +0000Discover heimdallhttps://dadrus.github.io/docs/getting_started/discover_heimdall/Wed, 29 Nov 2023 22:03:28 +0200https://dadrus.github.io/docs/getting_started/discover_heimdall/<div class="sect1"> <h2 id="_what_is_heimdall">What is heimdall?</h2> <div class="sectionbody"> <div class="paragraph"> diff --git a/dev/docs/mechanisms/finalizers/index.html b/dev/docs/mechanisms/finalizers/index.html index 93659d8c7..cb0d8577f 100644 --- a/dev/docs/mechanisms/finalizers/index.html +++ b/dev/docs/mechanisms/finalizers/index.html @@ -21,7 +21,7 @@ config: cookies: user_id_cookie: '{{ quote .Subject.ID }}' - user_email_cookie: '{{ index .Subject.Attributes "email" | quote }}'

JWT

This finalizer enables transformation of the Subject and the Outputs objects as custom claims into a token in a JWT format, which is then made available to your upstream service in either the HTTP Authorization header with Bearer scheme set, or in a custom header. Your upstream service can then verify the signature of the JWT by making use of heimdall’s JWKS endpoint to retrieve the required public keys/certificates from.

To enable the usage of this finalizer, you have to set the type property to jwt.

Configuration using the config property is optional. Following properties are available:

  • signer: Signer (mandatory, not overridable)

    The configuration of the key material used for signature creation purposes, as well as the name used for the iss claim.

  • claims: string (optional, overridable)

    Your template with custom claims, you would like to add to the JWT (See also Templating).

  • ttl: Duration (optional, overridable)

    Defines how long the JWT should be valid. Defaults to 5 minutes. Heimdall sets the iat and the nbf claims to the current system time. The value of the exp claim is then influenced by the ttl property.

  • header: object (optional, not overridable)

    Defines the name and scheme to be used for the header. Defaults to Authorization with scheme Bearer. If defined, the name property must be set. If scheme is not defined, no scheme will be prepended to the resulting JWT.

The generated JWT is always cached until 5 seconds before its expiration. The cache key is calculated from the entire configuration of the finalizer instance and the available information about the current subject.

Example 4. JWT finalizer configuration
id: jwt_finalizer
+    user_email_cookie: '{{ index .Subject.Attributes "email" | quote }}'

JWT

This finalizer enables transformation of the Subject and the Outputs objects into custom claims within a JWT. The resulting token is then made available to your upstream service in either the HTTP Authorization header (using the Bearer scheme) or in a custom header. Your upstream service can verify the JWT’s signature using heimdall’s JWKS endpoint to retrieve the necessary public keys/certificates.

To enable this finalizer, set the type property to jwt.

Configuration using the config property is mandatory. The following properties are available:

  • signer: Signer (mandatory, not overridable)

    Defines the key material for signing the JWT, as well as the iss claim.

  • claims: string (optional, overridable)

    A template specifying custom claims for the JWT. The template can use Values, Outputs, and Subject objects.

  • values: map of strings (optional, overridable)

    A key-value map accessible as Values in the template engine for rendering claims. Values in this map can also be templated with access to Subject and Outputs.

  • ttl: Duration (optional, overridable)

    Defines the JWT’s validity period. Defaults to 5 minutes. Heimdall automatically sets the iat and nbf claims to the current system time, and exp is calculated based on the ttl value.

  • header: object (optional, not overridable)

    Specifies the HTTP header name and optional scheme for passing the JWT. Defaults to Authorization with scheme Bearer. If defined, name is required, and if scheme is omitted, the JWT is set as a raw value.

The generated JWT is cached until 5 seconds before expiration. The cache key is computed based on the finalizer’s configuration, the Subject, and the Outputs attributes.

Example 4. JWT finalizer configuration
id: jwt_finalizer
 type: jwt
 config:
   ttl: 5m
@@ -32,8 +32,18 @@
       {{ $user_name := .Subject.Attributes.identity.user_name -}}
       "email": {{ quote .Subject.Attributes.identity.email }},
       "email_verified": {{ .Subject.Attributes.identity.email_verified }},
-      "name": {{ if $user_name }}{{ quote $user_name }}{{ else }}{{ quote $email }}{{ end }}
-    }

OAuth2 Client Credentials

This finalizer drives the OAuth2 Client Credentials Grant flow to obtain a token, which should be used for communication with the upstream service. By default, as long as not otherwise configured (see the options below), the obtained token is made available to your upstream service in the HTTP Authorization header with Bearer scheme set. Unlike the other finalizers, it does not have access to any objects created by the rule execution pipeline.

To enable the usage of this finalizer, you have to set the type property to oauth2_client_credentials.

Configuration using the config property is mandatory. Following properties are available:

  • token_url: string (mandatory, not overridable)

    The token endpoint of the authorization server.

  • client_id: string (mandatory, not overridable)

    The client identifier for heimdall.

  • client_secret: string (mandatory, not overridable)

    The client secret for heimdall.

  • auth_method: string (optional, not overridable)

    The authentication method to be used according to RFC 6749, Client Password. Can be one of

    • basic_auth (default if auth_method is not set): With that authentication method, the "application/x-www-form-urlencoded" encoded values of client_id and client_secret are sent to the authorization server via the Authorization header using the Basic scheme.

    • request_body: With that authentication method the client_id and client_secret are sent in the request body together with the other parameters (e.g. scopes) defined by the flow.

      Usage of request_body authentication method is not recommended and should be avoided.
  • scopes: string array (optional, overridable)

    The scopes required for the access token.

  • cache_ttl: Duration (optional, overridable)

    How long to cache the token received from the token endpoint. Defaults to the token expiration information from the token endpoint (the value of the expires_in field) if present. If the token expiration inforation is not present and cache_ttl is not configured, the received token is not cached. If the token expiration information is present in the response and cache_ttl is configured the shorter value is taken. If caching is enabled, the token is cached until 5 seconds before its expiration. To disable caching, set it to 0s. The cache key calculation is based on the entire oauth2_client_credentials configuration without considering the header property.

  • header: object (optional, overridable)

    Defines the name and scheme to be used for the header. Defaults to Authorization with scheme Bearer. If defined, the name property must be set. If scheme is not defined, no scheme will be prepended to the resulting JWT.

Example 5. OAuth2 Client Credentials finalizer configuration
id: get_token
+      "name": {{ if $user_name }}{{ quote $user_name }}{{ else }}{{ quote $email }}{{ end }},
+      "extra": {{ .Values | toJson }}
+    }

In a rule that references the jwt_finalizer, additional claims can be dynamically inserted into the "extra" claim without redefining claims:

- id: some_rule
+  # Other rule properties
+  execute:
+  - # Other mechanisms
+  - finalizer: jwt_finalizer
+    config:
+      values:
+        foo: bar
+        user_id: '{{ .Subject.ID }}'
+  - # Other mechanisms

OAuth2 Client Credentials

This finalizer drives the OAuth2 Client Credentials Grant flow to obtain a token, which should be used for communication with the upstream service. By default, as long as not otherwise configured (see the options below), the obtained token is made available to your upstream service in the HTTP Authorization header with Bearer scheme set. Unlike the other finalizers, it does not have access to any objects created by the rule execution pipeline.

To enable the usage of this finalizer, you have to set the type property to oauth2_client_credentials.

Configuration using the config property is mandatory. Following properties are available:

  • token_url: string (mandatory, not overridable)

    The token endpoint of the authorization server.

  • client_id: string (mandatory, not overridable)

    The client identifier for heimdall.

  • client_secret: string (mandatory, not overridable)

    The client secret for heimdall.

  • auth_method: string (optional, not overridable)

    The authentication method to be used according to RFC 6749, Client Password. Can be one of

    • basic_auth (default if auth_method is not set): With that authentication method, the "application/x-www-form-urlencoded" encoded values of client_id and client_secret are sent to the authorization server via the Authorization header using the Basic scheme.

    • request_body: With that authentication method the client_id and client_secret are sent in the request body together with the other parameters (e.g. scopes) defined by the flow.

      Usage of request_body authentication method is not recommended and should be avoided.
  • scopes: string array (optional, overridable)

    The scopes required for the access token.

  • cache_ttl: Duration (optional, overridable)

    How long to cache the token received from the token endpoint. Defaults to the token expiration information from the token endpoint (the value of the expires_in field) if present. If the token expiration inforation is not present and cache_ttl is not configured, the received token is not cached. If the token expiration information is present in the response and cache_ttl is configured the shorter value is taken. If caching is enabled, the token is cached until 5 seconds before its expiration. To disable caching, set it to 0s. The cache key calculation is based on the entire oauth2_client_credentials configuration without considering the header property.

  • header: object (optional, overridable)

    Defines the name and scheme to be used for the header. Defaults to Authorization with scheme Bearer. If defined, the name property must be set. If scheme is not defined, no scheme will be prepended to the resulting JWT.

Example 5. OAuth2 Client Credentials finalizer configuration
id: get_token
 type: oauth2_client_credentials
 config:
   cache_ttl: 5m
@@ -46,6 +56,6 @@
   auth_method: basic_auth
   scopes:
     - foo
-    - bar

Last updated on Jun 18, 2024


Last updated on Feb 18, 2025


\ No newline at end of file diff --git a/dev/docs/mechanisms/index.xml b/dev/docs/mechanisms/index.xml index d59d720de..dbe124660 100644 --- a/dev/docs/mechanisms/index.xml +++ b/dev/docs/mechanisms/index.xml @@ -1,4 +1,4 @@ -Mechanisms on Heimdallhttps://dadrus.github.io/docs/mechanisms/Recent content in Mechanisms on HeimdallHugoen-usMon, 17 Feb 2025 11:36:59 +0000Cataloguehttps://dadrus.github.io/docs/mechanisms/catalogue/Thu, 11 Jan 2024 15:01:21 +0200https://dadrus.github.io/docs/mechanisms/catalogue/<div class="paragraph"> +Mechanisms on Heimdallhttps://dadrus.github.io/docs/mechanisms/Recent content in Mechanisms on HeimdallHugoen-usTue, 18 Feb 2025 15:31:53 +0000Cataloguehttps://dadrus.github.io/docs/mechanisms/catalogue/Thu, 11 Jan 2024 15:01:21 +0200https://dadrus.github.io/docs/mechanisms/catalogue/<div class="paragraph"> <p>As described in <a href="../../docs/concepts/mechanisms/">Concepts</a> section, mechanisms must be defined and configured before these can be used in rules. That is happening in the so-called mechanisms catalogue. On start up heimdall instantiates all defined and configured mechanisms and makes these available for usage in rules.</p> </div> <div class="sect1"> diff --git a/dev/docs/operations/index.xml b/dev/docs/operations/index.xml index abea1cb79..3e060e800 100644 --- a/dev/docs/operations/index.xml +++ b/dev/docs/operations/index.xml @@ -1,4 +1,4 @@ -Operations on Heimdallhttps://dadrus.github.io/docs/operations/Recent content in Operations on HeimdallHugoen-usMon, 17 Feb 2025 11:36:59 +0000Configurationhttps://dadrus.github.io/docs/operations/configuration/Fri, 08 Jul 2022 09:16:36 +0200https://dadrus.github.io/docs/operations/configuration/<div class="paragraph"> +Operations on Heimdallhttps://dadrus.github.io/docs/operations/Recent content in Operations on HeimdallHugoen-usTue, 18 Feb 2025 15:31:53 +0000Configurationhttps://dadrus.github.io/docs/operations/configuration/Fri, 08 Jul 2022 09:16:36 +0200https://dadrus.github.io/docs/operations/configuration/<div class="paragraph"> <p>Configuration in heimdall can refer to two different things:</p> </div> <div class="ulist"> diff --git a/dev/docs/rules/index.xml b/dev/docs/rules/index.xml index f9bcd308e..e20770a5f 100644 --- a/dev/docs/rules/index.xml +++ b/dev/docs/rules/index.xml @@ -1,4 +1,4 @@ -Rules on Heimdallhttps://dadrus.github.io/docs/rules/Recent content in Rules on HeimdallHugoen-usMon, 17 Feb 2025 11:36:59 +0000Regular Rulehttps://dadrus.github.io/docs/rules/regular_rule/Thu, 09 Jun 2022 22:13:32 +0200https://dadrus.github.io/docs/rules/regular_rule/<div class="paragraph"> +Rules on Heimdallhttps://dadrus.github.io/docs/rules/Recent content in Rules on HeimdallHugoen-usTue, 18 Feb 2025 15:31:53 +0000Regular Rulehttps://dadrus.github.io/docs/rules/regular_rule/Thu, 09 Jun 2022 22:13:32 +0200https://dadrus.github.io/docs/rules/regular_rule/<div class="paragraph"> <p>In the simplest case, a regular rule reuses mechanisms from the previously defined <a href="../../docs/mechanisms/catalogue/">catalogue</a> in its pipelines. In more complex scenarios, a rule can reconfigure parts of the mechanisms being used. The specific parts that can be reconfigured or overridden depend on the mechanism itself and are described in the mechanism-specific documentation. Reconfiguration is always limited to the particular rule’s pipeline and does not affect other rules.</p> </div> <div class="sect1"> diff --git a/dev/docs/services/index.xml b/dev/docs/services/index.xml index 0f140f775..cd70540fc 100644 --- a/dev/docs/services/index.xml +++ b/dev/docs/services/index.xml @@ -1,4 +1,4 @@ -Services on Heimdallhttps://dadrus.github.io/docs/services/Recent content in Services on HeimdallHugoen-usMon, 17 Feb 2025 11:36:59 +0000Main Servicehttps://dadrus.github.io/docs/services/main/Thu, 09 Jun 2022 18:55:45 +0200https://dadrus.github.io/docs/services/main/<div class="paragraph"> +Services on Heimdallhttps://dadrus.github.io/docs/services/Recent content in Services on HeimdallHugoen-usTue, 18 Feb 2025 15:31:53 +0000Main Servicehttps://dadrus.github.io/docs/services/main/Thu, 09 Jun 2022 18:55:45 +0200https://dadrus.github.io/docs/services/main/<div class="paragraph"> <p>To make use of this service you have to start heimdall with either <code>heimdall serve proxy</code> or <code>heimdall serve decision</code>. By default, heimdall listens on <code>0.0.0.0:4455</code> endpoint for incoming requests and also configures useful defaults. You can, and should however adjust the configuration for your needs.</p> </div> <div class="sect1"> diff --git a/dev/guides/authn/index.xml b/dev/guides/authn/index.xml index 081357b53..434ad3a1e 100644 --- a/dev/guides/authn/index.xml +++ b/dev/guides/authn/index.xml @@ -1,4 +1,4 @@ -Authentication Protocols & Services on Heimdallhttps://dadrus.github.io/guides/authn/Recent content in Authentication Protocols & Services on HeimdallHugoen-usMon, 17 Feb 2025 11:36:59 +0000First-Party Authentication with OpenID Connecthttps://dadrus.github.io/guides/authn/oidc_first_party_auth/Fri, 04 Nov 2022 09:00:41 +0200https://dadrus.github.io/guides/authn/oidc_first_party_auth/<div class="paragraph"> +Authentication Protocols & Services on Heimdallhttps://dadrus.github.io/guides/authn/Recent content in Authentication Protocols & Services on HeimdallHugoen-usTue, 18 Feb 2025 15:31:53 +0000First-Party Authentication with OpenID Connecthttps://dadrus.github.io/guides/authn/oidc_first_party_auth/Fri, 04 Nov 2022 09:00:41 +0200https://dadrus.github.io/guides/authn/oidc_first_party_auth/<div class="paragraph"> <p>By the end of this guide, you’ll have a functional setup where heimdall uses <a href="https://www.keycloak.org/">Keycloak</a> to authenticate users and route requests based on their authentication status and roles for role-based access control.</p> </div> <div class="paragraph"> diff --git a/dev/guides/authz/index.xml b/dev/guides/authz/index.xml index 9daa1ab03..dff8f22f6 100644 --- a/dev/guides/authz/index.xml +++ b/dev/guides/authz/index.xml @@ -1,4 +1,4 @@ -Authorization Services on Heimdallhttps://dadrus.github.io/guides/authz/Recent content in Authorization Services on HeimdallHugoen-usMon, 17 Feb 2025 11:36:59 +0000Integration with OPAhttps://dadrus.github.io/guides/authz/opa/Fri, 04 Nov 2022 09:00:41 +0200https://dadrus.github.io/guides/authz/opa/<div class="paragraph"> +Authorization Services on Heimdallhttps://dadrus.github.io/guides/authz/Recent content in Authorization Services on HeimdallHugoen-usTue, 18 Feb 2025 15:31:53 +0000Integration with OPAhttps://dadrus.github.io/guides/authz/opa/Fri, 04 Nov 2022 09:00:41 +0200https://dadrus.github.io/guides/authz/opa/<div class="paragraph"> <p>The <a href="../../docs/getting_started/protect_an_app/">Protect an Application</a> quickstart guide, describing the steps required to protect an application with heimdall, shows already how <a href="https://www.openpolicyagent.org/">OPA</a> can be used with heimdall. This document provides some further examples.</p> </div> <div class="sect1"> diff --git a/dev/guides/proxies/index.xml b/dev/guides/proxies/index.xml index e5405b23a..b9f89fa40 100644 --- a/dev/guides/proxies/index.xml +++ b/dev/guides/proxies/index.xml @@ -1,4 +1,4 @@ -API Gateways & Proxies on Heimdallhttps://dadrus.github.io/guides/proxies/Recent content in API Gateways & Proxies on HeimdallHugoen-usMon, 17 Feb 2025 11:36:59 +0000Caddy Integrationhttps://dadrus.github.io/guides/proxies/caddy/Mon, 17 Feb 2025 10:43:16 +0200https://dadrus.github.io/guides/proxies/caddy/<div class="paragraph"> +API Gateways & Proxies on Heimdallhttps://dadrus.github.io/guides/proxies/Recent content in API Gateways & Proxies on HeimdallHugoen-usTue, 18 Feb 2025 15:31:53 +0000Caddy Integrationhttps://dadrus.github.io/guides/proxies/caddy/Mon, 17 Feb 2025 10:43:16 +0200https://dadrus.github.io/guides/proxies/caddy/<div class="paragraph"> <p><a href="https://caddyserver.com">Caddy</a> is a modern web server and reverse proxy known for its automatic HTTPS and simplicity. Heimdall can be integrated with Caddy using the <a href="https://caddyserver.com/docs/caddyfile/directives/forward_auth">forward_auth</a> directive. If heimdall responds with a 2XX status code, Caddy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.</p> </div> <div class="sect1"> diff --git a/dev/index.json b/dev/index.json index 8c583e6b2..86b9426e1 100644 --- a/dev/index.json +++ b/dev/index.json @@ -1 +1 @@ -[{"categories":null,"content":" What is heimdall? Heimdall is a cloud native identity aware proxy and access control decision service inspired by the Zero Trust idea. It brings together authentication and authorization systems and can be thought as an orchestrator for these in front of your services, allowing however completely retaining control even without the need for any type of maintenance in your own code.\nYou can use it\nintegrated into available proxies and API gateways, allowing implementation of Edge-level Authorization Architectures, or\nstand alone as an authentication \u0026amp; authorization proxy\nBoth approaches can help you scaling and securing you services by transparently adding security capabilities and secure defaults related to authentication and authorization.\nIf you want to know more about Edge-level Authorization Architecture, the Blog post from Netflix is a highly recommended read Typical challenges A typical (monolithic) system, or named it service, has not only to deal with the actual business logic, but also with authentication and authorization requirements (among other non-functional requirements) as depicted in the figure below.\nFigure 1. A typical monolithic system What do we have here?\nTo cover authentication requirements, that service will make use of some identity management system to verify the request authentication status.\nThe existing authorization requirements will most probably result in if else statements in code. Even such approaches are straight forward and easy to implement on the first sight, these are not easy to maintain and have many drawbacks (e.g. testing of particular use cases), and it becomes even more challenging when entering microservices.\nHow does it look then if we have microservices?\nNot every microservice will hold the entire information required for authorization purposes.\nSo, there will be a need to communicate to other services to get the required contextual information about the authenticated subject to be able to take the required authorization decision.\nThe management and maintenance of the authorization requirements will become even more challenging, as the implementation of these will usually be scattered across many services.\nTo overcome these dependencies, organizations either start pushing that contextual information into the identity management system, making it a god system with all resulting negative effects, or start using special purpose authorization systems, allowing managing the corresponding authorization policies outside the code.\nEven that approach reduces dependencies between the services and also the time to market, it introduces a new dependency, which all, or almost all services must make use of. And, most probably, the authorization system will also need to somehow retrieve contextual information for authorization policy evaluation purposes.\nAnd we just started to scratch the top of the iceberg. What if our system, comprised from these microservices is implemented in different languages? Even there are many libraries and also frameworks addressing authentication challenges, usually we just want to make the lives of our developers easier by providing components, which work the same way for each and every language. So the setup depicted above, well become similar to the one depicted below.\nFigure 2. Typical microservice deployment scenario Here, a new authentication proxy, typically deployed as a sidecar with each microservice (sometimes also as a central proxy), is introduced taking over the responsibility for the existing authentication challenges and unifying the corresponding implementation. But there are still many drawbacks and limitations, like those addressed by the following questions\nWhat if there is a need to have multiple identity management systems, e.g. one for the customers and one for accessing administrative or backoffice related functionality of the system?\nWhat if there is a need to migrate from one authentication or authorization system to another?\nWhat if there is a need to open the existing APIs?\nWhat if there is a need to support multiple different clients, like browsers, like mobile apps, IoT devices, etc?\nWhat if the business decides to change the existing authorization requirements, like introduction of a new subscription model, or alike, which would require additional information about our user, resulting in yet another dependency to some further service?\nWhat if depending on the client, we need completely different authentication strategies or even protocols, like OAuth2 or OpenID Connect in one case, mTLS in another case and cookie based approach and yet another case?\nHow to ensure, that our microservice code does not implement shortcuts and thus does not compromise the security of the entire system? (And there are diverse options achieving that)\n…​\nThis is by far not an exhaustive list. But the main question related to it is what does all of that mean in sense of coordination-, implementation efforts and time-to-market?\nHeimdall to the Rescue This is exactly where heimdall can step in and help you to address these challenges, reduce the complexity of your code, free resources, increase your time to market and make your system more secure.\nIf you let heimdall care about most of the existing authentication and authorization challenges, our new setup would then look as depicted below.\nFigure 3. Heimdall based deployment scenario This way you let heimdall orchestrate existing authentication and authorization systems and also provide the information about the authenticated and authorized subjects to your microservice in a unified format completely independent of the used authentication strategy or protocol.\nThere is however still the need to perform some type of authorization logic in your microservice code. Especially if we talk about read requests (most probably you want to provide different representation of the requested resource based on the authorization status). But it is much simpler, and it gives you much more freedom compared to all previous approaches.\nYou don’t necessary need to replace proxies, gateways, ingress controller, or alike currently in place in your infrastructure with heimdall. You can easily integrate heimdall with them to achieve the functionality depicted above. How it works Heimdall intercepts all your application related HTTP(s) traffic, allowing a broad set of identity and application aware authentication and authorization features based on the rules you specify and deploy together with your particular service. These rules let heimdall route each request through a service or even endpoint specific authentication and authorization pipeline as depicted in diagram below.\nFigure 4. Authentication \u0026amp; Authorization Pipeline This pipeline ensures that, according to the needs of the particular backend service endpoint,\neach request is authenticated (so, you know who the subject of the request is) by making use of the available identity management systems,\nthe required contextual information about the subject is available (like e.g. current location based on IP, roles or groups membership information, etc.) by retrieving it from any possible API, so that\nthe subject can be and is authorized by your authorization system, or even directly by heimdall and\nthe information about the subject is transformed into a format, required by the backend service. So that despite the used authentication or authorization system or protocol, the subject information is always provided in the same stable representation to your microservice.\nNext Steps Take a look and experiment\nThe Protect an Application chapter describes two setups, allowing getting your hands \u0026#34;dirty\u0026#34; and familiarizing with the concepts implemented by heimdall.\nJoin the community\nChat interactively in our Discord and ask your questions :)\nLearn the concepts\nThere is an entire section which describes the concepts, users should understand. Start with Pipelines, which deals with the \u0026#34;Client Request Journey\u0026#34; depicted above in great detail and work you through until the Operating Modes, which will reveal you the possible integration options.\nCheck the guides\nMany guides have been written to support you in you endeavour with heimdall, including working examples, which you can find on GitHub. There are also many examples in particular chapters.\nImplement your requirements and bring heimdall to production\nInstall heimdall into your \u0026#34;playground\u0026#34; environment, implement rules by making use of mechanisms reflecting your requirements, secure your setup and bring it to production.\n","description":"This page gives an overview about heimdall, the challenges it addresses and how it does so. In addition, you can find some recommendations on where to look next.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_what_is_heimdall\"\u003eWhat is heimdall?\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall is a cloud native identity aware proxy and access control decision service inspired by the Zero Trust idea. It brings together authentication and authorization systems and can be thought as an orchestrator for these in front of your services, allowing however completely retaining control even without the need for any type of maintenance in your own code.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can use it\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eintegrated into available proxies and API gateways, allowing implementation of Edge-level Authorization Architectures, or\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003estand alone as an authentication \u0026amp; authorization proxy\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBoth approaches can help you scaling and securing you services by transparently adding security capabilities and secure defaults related to authentication and authorization.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you want to know more about Edge-level Authorization Architecture, the \u003ca href=\"https://netflixtechblog.com/edge-authentication-and-token-agnostic-identity-propagation-514e47e0b602\"\u003eBlog post\u003c/a\u003e from Netflix is a highly recommended read\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_typical_challenges\"\u003eTypical challenges\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA typical (monolithic) system, or named it service, has not only to deal with the actual business logic, but also with authentication and authorization requirements (among other non-functional requirements) as depicted in the figure below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-d2f5c648e6dd3a2376f4fc340284540c.svg\" alt=\"Diagram\" width=\"920\" height=\"518\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 1. A typical monolithic system\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhat do we have here?\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eTo cover authentication requirements, that service will make use of some identity management system to verify the request authentication status.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe existing authorization requirements will most probably result in if else statements in code. Even such approaches are straight forward and easy to implement on the first sight, these are not easy to maintain and have many drawbacks (e.g. testing of particular use cases), and it becomes even more challenging when entering microservices.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow does it look then if we have microservices?\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eNot every microservice will hold the entire information required for authorization purposes.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eSo, there will be a need to communicate to other services to get the required contextual information about the authenticated subject to be able to take the required authorization decision.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe management and maintenance of the authorization requirements will become even more challenging, as the implementation of these will usually be scattered across many services.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo overcome these dependencies, organizations either start pushing that contextual information into the identity management system, making it a god system with all resulting negative effects, or start using special purpose authorization systems, allowing managing the corresponding authorization policies outside the code.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEven that approach reduces dependencies between the services and also the time to market, it introduces a new dependency, which all, or almost all services must make use of. And, most probably, the authorization system will also need to somehow retrieve contextual information for authorization policy evaluation purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAnd we just started to scratch the top of the iceberg. What if our system, comprised from these microservices is implemented in different languages? Even there are many libraries and also frameworks addressing authentication challenges, usually we just want to make the lives of our developers easier by providing components, which work the same way for each and every language. So the setup depicted above, well become similar to the one depicted below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_fig_typical_deployment_scenario\" class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-2ad275416d51525f3aa30125819e84af.svg\" alt=\"Diagram\" width=\"1150\" height=\"518\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 2. Typical microservice deployment scenario\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, a new authentication proxy, typically deployed as a sidecar with each microservice (sometimes also as a central proxy), is introduced taking over the responsibility for the existing authentication challenges and unifying the corresponding implementation. But there are still many drawbacks and limitations, like those addressed by the following questions\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if there is a need to have multiple identity management systems, e.g. one for the customers and one for accessing administrative or backoffice related functionality of the system?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if there is a need to migrate from one authentication or authorization system to another?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if there is a need to open the existing APIs?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if there is a need to support multiple different clients, like browsers, like mobile apps, IoT devices, etc?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if the business decides to change the existing authorization requirements, like introduction of a new subscription model, or alike, which would require additional information about our user, resulting in yet another dependency to some further service?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if depending on the client, we need completely different authentication strategies or even protocols, like OAuth2 or OpenID Connect in one case, mTLS in another case and cookie based approach and yet another case?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eHow to ensure, that our microservice code does not implement shortcuts and thus does not compromise the security of the entire system? (And there are diverse options achieving that)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e…​\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis is by far not an exhaustive list. But the main question related to it is what does all of that mean in sense of coordination-, implementation efforts and time-to-market?\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_heimdall_to_the_rescue\"\u003eHeimdall to the Rescue\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis is exactly where heimdall can step in and help you to address these challenges, reduce the complexity of your code, free resources, increase your time to market and make your system more secure.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you let heimdall care about most of the existing authentication and authorization challenges, our new setup would then look as depicted below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-3bcdc8fa896af7ae13650b8d7e6cf707.svg\" alt=\"Diagram\" width=\"890\" height=\"532\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 3. Heimdall based deployment scenario\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis way you let heimdall orchestrate existing authentication and authorization systems and also provide the information about the authenticated and authorized subjects to your microservice in a unified format completely independent of the used authentication strategy or protocol.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere is however still the need to perform some type of authorization logic in your microservice code. Especially if we talk about read requests (most probably you want to provide different representation of the requested resource based on the authorization status). But it is much simpler, and it gives you much more freedom compared to all previous approaches.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nYou don’t necessary need to replace proxies, gateways, ingress controller, or alike currently in place in your infrastructure with heimdall. You can easily integrate heimdall with them to achieve the functionality depicted above.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_how_it_works\"\u003eHow it works\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall intercepts all your application related HTTP(s) traffic, allowing a broad set of identity and application aware authentication and authorization features based on the rules you specify and deploy together with your particular service. These rules let heimdall route each request through a service or even endpoint specific authentication and authorization pipeline as depicted in diagram below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_fig_heimdall_request_pipeline\" class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-92616c018b7cc4e879c86947d2cf5d7c.svg\" alt=\"Diagram\" width=\"1290\" height=\"294\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 4. Authentication \u0026amp; Authorization Pipeline\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis pipeline ensures that, according to the needs of the particular backend service endpoint,\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eeach request is authenticated (so, you know who the subject of the request is) by making use of the available identity management systems,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe required contextual information about the subject is available (like e.g. current location based on IP, roles or groups membership information, etc.) by retrieving it from any possible API, so that\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe subject can be and is authorized by your authorization system, or even directly by heimdall and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe information about the subject is transformed into a format, required by the backend service. So that despite the used authentication or authorization system or protocol, the subject information is always provided in the same stable representation to your microservice.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_next_steps\"\u003eNext Steps\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eTake a look and experiment\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"/docs/getting_started/protect_an_app/\"\u003eProtect an Application\u003c/a\u003e chapter describes two setups, allowing getting your hands \u0026#34;dirty\u0026#34; and familiarizing with the concepts implemented by heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eJoin the community\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eChat interactively in our \u003ca href=\"https://discord.gg/qQgg8xKuyb\"\u003eDiscord\u003c/a\u003e and ask your questions :)\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eLearn the concepts\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere is an entire section which describes the concepts, users should understand. Start with \u003ca href=\"/docs/concepts/pipelines/\"\u003ePipelines\u003c/a\u003e, which deals with the \u0026#34;Client Request Journey\u0026#34; depicted above in great detail and work you through until the \u003ca href=\"/docs/concepts/operating_modes/\"\u003eOperating Modes\u003c/a\u003e, which will reveal you the possible integration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eCheck the guides\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eMany \u003ca href=\"/guides/\"\u003eguides\u003c/a\u003e have been written to support you in you endeavour with heimdall, including working examples, which you can find on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e. There are also many examples in particular chapters.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eImplement your requirements and bring heimdall to production\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"/docs/getting_started/installation/\"\u003eInstall\u003c/a\u003e heimdall into your \u0026#34;playground\u0026#34; environment, implement \u003ca href=\"/docs/rules/regular_rule/\"\u003erules\u003c/a\u003e by making use of \u003ca href=\"/docs/mechanisms/catalogue/\"\u003emechanisms\u003c/a\u003e reflecting your requirements, \u003ca href=\"/docs/operations/security/\"\u003esecure\u003c/a\u003e your setup and bring it to production.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Getting Started"],"tags":null,"title":"Discover heimdall","url":"/docs/getting_started/discover_heimdall/"},{"categories":null,"content":" Source Code You can always build a copy of heimdall by following the following instructions for your OS/environment.\nPrerequisites git\nThe Go programming language \u0026gt;= 1.24\nDownload Retrieve the latest copy of heimdall source code by cloning the git repository\n$ git clone git@github.com:dadrus/heimdall.git Build with go Build using a single line with go build\n$ CGO_ENABLED=0 go build -trimpath -ldflags=\u0026#34;-buildid= -w -s -X github.com/dadrus/heimdall/version.Version==my-custom-build\u0026#34; The flags are set by intention. Using -trimpath and -buildid= as part of the -ldflags argument ensures the build is reproducible (See also Reproducible Builds). Other flags remove unused symbols and debug information.\nBinary Prebuild binaries are available with every released version on GitHub, as well as for every merged PR to the main branch. The version of the latter is set to the git SHA1. Supported operating systems/architectures are:\ndarwin/amd64\ndarwin/arm64\nlinux/amd64\nlinux/arm64\nlinux/armv6\nlinux/armv7\nwindows/amd64\nFor Linux and Darwin the binaries are archived with tar.gz and for Windows with zip. All archives are signed (see also Verifying Heimdall Binaries and Container Images section on how to verify the signatures).\nDownload Retrieve the desired released version of heimdall binary for your operating system/architecture\nARCH=[your arch] OS=[your os] VERSION=[desired version] curl -L https://github.com/dadrus/heimdall/releases/download/${VERSION}/heimdall-${VERSION}-${OS}-${ARCH}.tar.gz \\ | tar -z -x Container Image Heimdall utilizes a minimal container multi-arch image which you can find on DockerHub, or on GHCR. As with Binary releases, heimdall can be pulled in several flavors. These are however currently limited to the Linux OS. Supported architectures are:\namd64\narm64\narm/v7\nAll container images are rootless - so heimdall will always run as a non-root user within the container. Since Heimdall does not have any dependencies, the images are distroless as well and contain only the binary of heimdall and the settings related to the OS user and group permissions, heimdall is running with.\nAs with the binary distribution, all container images are signed (see also Verifying Heimdall Binaries and Container Images section on how to verify the signatures).\nPrerequisites Docker, Podman, or other container runtime of your choice (examples are however using docker).\nPull Image The steps below will pull the images from DockerHub. If you want to pull them from GHCR, specify the ghcr.io registry in front of the repository.\nFollowing tag patterns exist:\nx.y.z[-\u0026lt;prerelease-identifier\u0026gt;] - will pull a specific tagged release.\n$ docker pull dadrus/heimdall:0.15.0 \u0026amp;\u0026amp; docker run dadrus/heimdall:0.15.0 --version heimdall version v0.15.0 latest - will pull the most recent tagged release.\n$ docker pull dadrus/heimdall:latest \u0026amp;\u0026amp; docker run dadrus/heimdall:latest --version heimdall version 0.15.0 Helm Chart Heimdall can be installed via a Helm chart with a few simple steps, depending on if you are deploying for the first time, or upgrading from an existing installation.\nPrerequisites A Kubernetes version \u0026gt;= 1.27\nHelm 3.0+\nAdding the Helm Repository The heimdall Helm Chart is published at https://dadrus.github.io/heimdall/charts. You can add this repo with the following command:\n$ helm repo add dadrus https://dadrus.github.io/heimdall/charts $ helm repo update Installing the Chart This chart expects a heimdall configuration file with authentication, authorization and so on mechanisms, required for your particular setup, which can be passed by using the -f heimdall.yaml flag during the installation.\nIf you need to override the name of the heimdall resources such as the deployment or services, the traditional nameOverride and fullnameOverride properties are supported.\nBy default, heimdall requires custom resource definitions (CRDs) installed in the cluster. The Helm client will install it for you.\nTo install the chart with the release name my-release (my-release is the name that you choose) and configure heimdall to operate in decision mode:\n$ helm install my-release -f heimdall.yaml dadrus/heimdall If you need proxy mode, install it with:\n$ helm install my-release -f heimdall.yaml --set operationMode=proxy dadrus/heimdall For more advanced configuration and details about helm values, please see the helm chart.\nPost-Install Steps Integration with Ingress After having installed heimdall, you have to integrate it with your ingress controller. For decision mode that means setting corresponding annotations on Ingress resources to let the traffic first be verified by heimdall before it is forwarded to the upstream services by the Ingress Controller.\nMetrics Collection Since heimdall is able to exposes a comprehensive set of Prometheus style metrics (See Metrics for details), you can, assuming you are running a Prometheus Operator in your cluster, create the following PodMonitor resource to enable metrics collection.\napiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: name: heimdall-pod-monitor labels: release: prometheus app.kubernetes.io/instance: my-release app.kubernetes.io/name: heimdall app.kubernetes.io/part-of: heimdall spec: selector: matchLabels: app.kubernetes.io/instance: my-release app.kubernetes.io/name: heimdall podMetricsEndpoints: - path: /metrics port: http-metrics scheme: http interval: 30s jobLabel: heimdall-pod-monitor namespaceSelector: matchNames: - default The definition of the PodMonitor above assumes, you’ve installed heimdall in the default namespace as shown in the Installing the Chart section. If this is not the case, you need to adjust the metadata property by adding the corresponding namespace information, as well as the namespaceSelector.\nIf your Prometheus deployment is not done through the operator, you don’t need to do anything, as the chart already sets the relevant annotations: prometheus.io/scrape, prometheus.io/path and prometheus.io/port.\n","description":"Heimdall is shipped in multiple formats and architectures to suit a variety of deployment patterns. The following chapters describe the available installation options.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_source_code\"\u003eSource Code\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can always build a copy of heimdall by following the following instructions for your OS/environment.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_prerequisites\"\u003ePrerequisites\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://git-scm.com/\"\u003egit\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ca href=\"https://go.dev/dl/\"\u003eGo\u003c/a\u003e programming language \u0026gt;= 1.24\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_download\"\u003eDownload\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRetrieve the latest copy of heimdall source code by cloning the git repository\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003egit clone git@github.com:dadrus/heimdall.git\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_build_with_go\"\u003eBuild with go\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBuild using a single line with \u003ccode\u003ego build\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ CGO_ENABLED\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e0 go build \u003cspan class=\"nt\"\u003e-trimpath\u003c/span\u003e \u003cspan class=\"nt\"\u003e-ldflags\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;-buildid= -w -s -X github.com/dadrus/heimdall/version.Version==my-custom-build\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe flags are set by intention. Using \u003ccode\u003e-trimpath\u003c/code\u003e and \u003ccode\u003e-buildid=\u003c/code\u003e as part of the \u003ccode\u003e-ldflags\u003c/code\u003e argument ensures the build is reproducible (See also \u003ca href=\"https://reproducible-builds.org/\"\u003eReproducible Builds\u003c/a\u003e). Other flags remove unused symbols and debug information.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_binary\"\u003eBinary\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePrebuild binaries are available with every released version on \u003ca href=\"https://github.com/dadrus/heimdall/releases/latest\"\u003eGitHub\u003c/a\u003e, as well as for every merged PR to the main branch. The version of the latter is set to the git SHA1. Supported operating systems/architectures are:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003edarwin/amd64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003edarwin/arm64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elinux/amd64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elinux/arm64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elinux/armv6\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elinux/armv7\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ewindows/amd64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor Linux and Darwin the binaries are archived with tar.gz and for Windows with zip. All archives are signed (see also \u003ca href=\"/docs/operations/security/#_verifying_heimdall_binaries_and_container_images\"\u003eVerifying Heimdall Binaries and Container Images\u003c/a\u003e section on how to verify the signatures).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_download_2\"\u003eDownload\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRetrieve the desired released version of heimdall binary for your operating system/architecture\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eARCH\u003c/span\u003e\u003cspan class=\"o\"\u003e=[\u003c/span\u003eyour \u003cspan class=\"nb\"\u003earch\u003c/span\u003e\u003cspan class=\"o\"\u003e]\u003c/span\u003e\n\u003cspan class=\"nv\"\u003eOS\u003c/span\u003e\u003cspan class=\"o\"\u003e=[\u003c/span\u003eyour os]\n\u003cspan class=\"nv\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"o\"\u003e=[\u003c/span\u003edesired version]\ncurl \u003cspan class=\"nt\"\u003e-L\u003c/span\u003e https://github.com/dadrus/heimdall/releases/download/\u003cspan class=\"k\"\u003e${\u003c/span\u003e\u003cspan class=\"nv\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"k\"\u003e}\u003c/span\u003e/heimdall-\u003cspan class=\"k\"\u003e${\u003c/span\u003e\u003cspan class=\"nv\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"k\"\u003e}\u003c/span\u003e-\u003cspan class=\"k\"\u003e${\u003c/span\u003e\u003cspan class=\"nv\"\u003eOS\u003c/span\u003e\u003cspan class=\"k\"\u003e}\u003c/span\u003e-\u003cspan class=\"k\"\u003e${\u003c/span\u003e\u003cspan class=\"nv\"\u003eARCH\u003c/span\u003e\u003cspan class=\"k\"\u003e}\u003c/span\u003e.tar.gz \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n | \u003cspan class=\"nb\"\u003etar\u003c/span\u003e \u003cspan class=\"nt\"\u003e-z\u003c/span\u003e \u003cspan class=\"nt\"\u003e-x\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_container_image\"\u003eContainer Image\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall utilizes a minimal container multi-arch image which you can find on \u003ca href=\"https://hub.docker.com/r/dadrus/heimdall\"\u003eDockerHub\u003c/a\u003e, or on \u003ca href=\"https://github.com/users/dadrus/packages?repo_name=heimdall\"\u003eGHCR\u003c/a\u003e. As with \u003ca href=\"#_binary\"\u003eBinary\u003c/a\u003e releases, heimdall can be pulled in several flavors. These are however currently limited to the Linux OS. Supported architectures are:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eamd64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003earm64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003earm/v7\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll container images are rootless - so heimdall will always run as a non-root user within the container. Since Heimdall does not have any dependencies, the images are distroless as well and contain only the binary of heimdall and the settings related to the OS user and group permissions, heimdall is running with.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with the binary distribution, all container images are signed (see also \u003ca href=\"/docs/operations/security/#_verifying_heimdall_binaries_and_container_images\"\u003eVerifying Heimdall Binaries and Container Images\u003c/a\u003e section on how to verify the signatures).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_prerequisites_2\"\u003ePrerequisites\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/install/\"\u003eDocker\u003c/a\u003e, \u003ca href=\"https://podman.io/\"\u003ePodman\u003c/a\u003e, or other container runtime of your choice (examples are however using docker).\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_pull_image\"\u003ePull Image\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe steps below will pull the images from \u003ca href=\"https://hub.docker.com/r/dadrus/heimdall\"\u003eDockerHub\u003c/a\u003e. If you want to pull them from \u003ca href=\"https://github.com/users/dadrus/packages?repo_name=heimdall\"\u003eGHCR\u003c/a\u003e, specify the \u003ccode\u003eghcr.io\u003c/code\u003e registry in front of the repository.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing tag patterns exist:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ex.y.z[-\u0026lt;prerelease-identifier\u0026gt;]\u003c/code\u003e - will pull a specific tagged release.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003edocker pull dadrus/heimdall:0.15.0 \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e docker run dadrus/heimdall:0.15.0 \u003cspan class=\"nt\"\u003e--version\u003c/span\u003e\nheimdall version v0.15.0\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elatest\u003c/code\u003e - will pull the most recent tagged release.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003edocker pull dadrus/heimdall:latest \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e docker run dadrus/heimdall:latest \u003cspan class=\"nt\"\u003e--version\u003c/span\u003e\nheimdall version 0.15.0\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_helm_chart\"\u003eHelm Chart\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall can be installed via a Helm chart with a few simple steps, depending on if you are deploying for the first time, or upgrading from an existing installation.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_prerequisites_3\"\u003ePrerequisites\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eA Kubernetes version \u0026gt;= 1.27\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://helm.sh/docs/intro/install/\"\u003eHelm\u003c/a\u003e 3.0+\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_adding_the_helm_repository\"\u003eAdding the Helm Repository\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe heimdall Helm Chart is published at \u003ccode\u003ehttps://dadrus.github.io/heimdall/charts\u003c/code\u003e. You can add this repo with the following command:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ehelm repo add dadrus https://dadrus.github.io/heimdall/charts\n\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ehelm repo update\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_installing_the_chart\"\u003eInstalling the Chart\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis chart expects a \u003ca href=\"/docs/operations/configuration/#_configuration_file\"\u003eheimdall configuration file\u003c/a\u003e with authentication, authorization and so on mechanisms, required for your particular setup, which can be passed by using the \u003ccode\u003e-f heimdall.yaml\u003c/code\u003e flag during the installation.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you need to override the name of the heimdall resources such as the deployment or services, the traditional \u003ccode\u003enameOverride\u003c/code\u003e and \u003ccode\u003efullnameOverride\u003c/code\u003e properties are supported.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy default, heimdall requires custom resource definitions (CRDs) installed in the cluster. The Helm client will install it for you.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo install the chart with the release name \u003ccode\u003emy-release\u003c/code\u003e (\u003ccode\u003emy-release\u003c/code\u003e is the name that you choose) and configure heimdall to operate in decision mode:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ehelm \u003cspan class=\"nb\"\u003einstall \u003c/span\u003emy-release \u003cspan class=\"nt\"\u003e-f\u003c/span\u003e heimdall.yaml dadrus/heimdall\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you need proxy mode, install it with:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ehelm \u003cspan class=\"nb\"\u003einstall \u003c/span\u003emy-release \u003cspan class=\"nt\"\u003e-f\u003c/span\u003e heimdall.yaml \u003cspan class=\"nt\"\u003e--set\u003c/span\u003e \u003cspan class=\"nv\"\u003eoperationMode\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003eproxy dadrus/heimdall\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor more advanced configuration and details about helm values, \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/charts/heimdall\"\u003eplease see the helm chart\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_post_install_steps\"\u003ePost-Install Steps\u003c/h3\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_integration_with_ingress\"\u003eIntegration with Ingress\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAfter having installed heimdall, you have to integrate it with your ingress controller. For decision mode that means setting corresponding annotations on Ingress resources to let the traffic first be verified by heimdall before it is forwarded to the upstream services by the Ingress Controller.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_metrics_collection\"\u003eMetrics Collection\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince heimdall is able to exposes a comprehensive set of Prometheus style metrics (See \u003ca href=\"/docs/operations/observability/#_metrics\"\u003eMetrics\u003c/a\u003e for details), you can, assuming you are running a \u003ca href=\"https://github.com/prometheus-operator/prometheus-operator\"\u003ePrometheus Operator\u003c/a\u003e in your cluster, create the following \u003ccode\u003ePodMonitor\u003c/code\u003e resource to enable metrics collection.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emonitoring.coreos.com/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ePodMonitor\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-pod-monitor\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003erelease\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eprometheus\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/instance\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-release\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/part-of\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eselector\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematchLabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/instance\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-release\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003epodMetricsEndpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/metrics\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp-metrics\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp\u003c/span\u003e\n \u003cspan class=\"na\"\u003einterval\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e30s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ejobLabel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-pod-monitor\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespaceSelector\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematchNames\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe definition of the \u003ccode\u003ePodMonitor\u003c/code\u003e above assumes, you’ve installed heimdall in the default namespace as shown in the \u003ca href=\"#_installing_the_chart\"\u003eInstalling the Chart\u003c/a\u003e section. If this is not the case, you need to adjust the \u003ccode\u003emetadata\u003c/code\u003e property by adding the corresponding \u003ccode\u003enamespace\u003c/code\u003e information, as well as the \u003ccode\u003enamespaceSelector\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf your Prometheus deployment is not done through the operator, you don’t need to do anything, as the chart already sets the relevant annotations: \u003ccode\u003eprometheus.io/scrape\u003c/code\u003e, \u003ccode\u003eprometheus.io/path\u003c/code\u003e and \u003ccode\u003eprometheus.io/port\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Getting Started"],"tags":null,"title":"Install heimdall","url":"/docs/getting_started/installation/"},{"categories":null,"content":" Overview In this guide, we’ll configure two setups to protect a service that exposes a few endpoints:\nThe /public endpoint is, as the name implies, public. Every request to it should be forwarded as is.\nThe /user endpoint should only be accessible to users with the user role.\nThe /admin endpoint should only be accessible to users with the admin role.\nThe /private endpoint, along with any other potentially exposed endpoints, should not be accessible at all. All requests to it should be rejected.\nFor authentication, we’ll use JWTs containing the respective roles. Authorization will be handled with the help of Open Policy Agent (OPA).\nIn both setups, we’ll create minimal but complete environments using Docker Compose with:\nTraefik as the edge proxy,\ncontainous/whoami (a service that echoes back everything it receives), mimicking our service exposing the endpoints described above,\nan NGINX server serving the public key for verifying the JWTs (mimicking the JWKS endpoint typically exposed by an OIDC provider),\nOPA, which evaluates the authorization policy,\nheimdall, orchestrating everything to enforce the above requirements.\nThis quickstart and others demonstrating different integration options are also available on GitHub. Prerequisites To follow this guide, you’ll need the following tools installed locally:\nDocker,\ndocker-compose, and\na text editor of your choice.\nConfigure Heimdall can be configured via environment variables, as well as using a configuration file. For simplicity, we’ll use a configuration file in this guide. Create a file named heimdall-config.yaml with the following contents:\nlog: (1) level: debug tracing: enabled: false metrics: enabled: false serve: (2) decision: trusted_proxies: - 0.0.0.0/0 mechanisms: (3) authenticators: - id: deny_all (4) type: unauthorized - id: anon (5) type: anonymous - id: jwt_auth (6) type: jwt config: jwks_endpoint: http://idp:8080/.well-known/jwks assertions: issuers: - demo_issuer authorizers: - id: opa (7) type: remote config: endpoint: http://opa:8181/v1/data/{{ .Values.policy }} payload: \u0026#34;{}\u0026#34; expressions: - expression: | Payload.result == true finalizers: - id: create_jwt (8) type: jwt config: signer: key_store: path: /etc/heimdall/signer.pem - id: noop (9) type: noop default_rule: (10) execute: - authenticator: deny_all - finalizer: create_jwt providers: file_system: (11) src: /etc/heimdall/rules.yaml watch: true 1 Since heimdall emits logs at the error level by default, and we want to monitor what’s happening, we’ll set the log level to debug. This way, we’ll not only see the results of a particular rule execution (which you would see with the info log level), but also detailed logs of what’s going on inside each rule. Additionally, we disable tracing and metrics collection, which are pulled by default to an OTEL agent, to avoid error messages related to the unavailability of the agent. For more information on available observability options, see the Observability chapter. 2 This configuration instructs heimdall to trust X-Forwarded-* headers from any source. We need this for integration with Traefik, which uses these headers while forwarding requests to heimdall. The IP address used depends on your local Docker configuration. Never use this in production - always restrict trusted IPs instead! Refer to the documentation on the trusted_proxies property and Security Considerations for more details. 3 Here, we define our catalogue of mechanisms to be used in upstream service-specific rules. In this case, we define authenticators, an authorizer, and finalizers. 4 These two lines define the unauthorized authenticator named deny_all, which rejects all requests. 5 These two lines define the anonymous authenticator named anon, which allows any request and creates a subject with the ID set to anonymous. You can find more information about the subject and other objects here. 6 This and the following lines define and configure the jwt authenticator named jwt_auth. With this configuration, it will check if a request contains an Authorization header with a bearer token in JWT format and validate it using key material fetched from the JWKS endpoint. It will reject requests without a valid JWT or create a subject with the sub claim set to the token’s sub value. All other claims will also be added to the subject’s attributes. 7 Here, we define and configure a remote authorizer named opa. Note how we allow for the overriding of particular settings, which will be specified below when we define the rules. 8 The following lines define the jwt finalizer. This configuration will generate a JWT from the subject object with standard claims, setting the sub claim to the subject’s ID. The key material used for signing is pulled from the referenced key store. 9 These two lines conclude the definition of our mechanisms catalogue and define the noop finalizer, which, as the name implies, does nothing. 10 With the mechanisms catalogue in place, we can now define a default rule. This rule will be triggered if no other rule matches the request. It also acts as a base for defining regular (upstream service-specific) rules. This rule defines a secure default authentication \u0026amp; authorization pipeline, which denies any request using the deny_all authenticator. If overridden by a regular rule, it will create a JWT using the jwt finalizer. 11 The last few lines configure the file_system provider, which allows loading regular rules from the file system. The provider is also configured to watch for changes, so you can modify the rules in real time. Create a file named signer.pem with the following content. This file is our key store with a private key, which you’ll see referenced in the configuration above.\n-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy 1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI zlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X XVwR/5tokqFVrFxt/5c1x7VdccF4nNM= -----END EC PRIVATE KEY----- Do not use this for purposes beyond this tutorial! Now, create a rule file named upstream-rules.yaml to implement the authentication and authorization requirements for your service. Copy the following contents into it:\nversion: \u0026#34;1alpha4\u0026#34; rules: - id: demo:public (1) match: routes: - path: /public forward_to: host: upstream:8081 execute: - authenticator: anon - finalizer: noop - id: demo:protected (2) match: routes: - path: /:user path_params: - name: user type: glob value: \u0026#34;{user,admin}\u0026#34; forward_to: host: upstream:8081 execute: - authenticator: jwt_auth - authorizer: opa config: values: policy: demo/can_access payload: | { \u0026#34;input\u0026#34;: { \u0026#34;role\u0026#34;: {{ quote .Subject.Attributes.role }}, \u0026#34;path\u0026#34;: {{ quote .Request.URL.Path }} } } 1 This rule matches the /public endpoint and forwards the request to our upstream service without performing any verification or transformation. 2 This rule matches the /user and /admin endpoints, handling both authentication and authorization steps. Since we don’t define a finalizer in the second rule’s pipeline, the default rule’s finalizer is reused. There is no need for additional rules, as the default rule will block requests to any other endpoints. Now that everything related to heimdall configuration is in place, let’s create a policy that OPA will use. Create a file named policy.rego with the following contents:\npackage demo default can_access = false (1) can_access { split(input.path, \u0026#34;/\u0026#34;)[1] == input.role } (2) Here, we define our policy can_access within the demo package. The policy is straightforward, evaluating to either true or false.\n1 By default, the can_access policy evaluates to false. 2 It evaluates to true only when the last path fragment of the request matches the user’s role. Now, let’s configure NGINX to expose a static endpoint that serves a JWKS document under the .well-known path. This will allow heimdall to verify the JWTs we will use. Create a file named idp.nginx with the following content:\nworker_processes 1; user nginx; pid /var/run/nginx.pid; events { worker_connections 1024; } http { keepalive_timeout 65; server { listen 8080; location /.well-known/jwks { default_type application/json; root /var/www/nginx; try_files /jwks.json =404; } } } In addition, create a file named jwks.json containing the public key needed to verify the tokens we will use.\n{ \u0026#34;keys\u0026#34;: [{ \u0026#34;use\u0026#34;:\u0026#34;sig\u0026#34;, \u0026#34;kty\u0026#34;:\u0026#34;EC\u0026#34;, \u0026#34;kid\u0026#34;:\u0026#34;key-1\u0026#34;, \u0026#34;crv\u0026#34;:\u0026#34;P-256\u0026#34;, \u0026#34;alg\u0026#34;:\u0026#34;ES256\u0026#34;, \u0026#34;x\u0026#34;:\u0026#34;cv6F6SgBSNWMZKdApZXSuPD6QPtvQyMpk-iRfZxT-vo\u0026#34;, \u0026#34;y\u0026#34;:\u0026#34;C1r3OClUvyDgmDQdvxMdB-ucmZ28b8s4uM4Yg-0BZZ4\u0026#34; }] } We will place it in the /var/www/nginx folder, as mentioned earlier, when we set up our environment.\nNow, let’s configure the environment. To run heimdall as a proxy, create or modify a docker-compose.yaml file. Be sure to update it with the correct paths to your heimdall-config.yaml, upstream-rules.yaml, policy.rego, idp.nginx, and jwks.json files created earlier.\nservices: heimdall: (1) image: dadrus/heimdall:dev ports: - \u0026#34;9090:4455\u0026#34; volumes: - ./heimdall-config.yaml:/etc/heimdall/config.yaml:ro - ./upstream-rules.yaml:/etc/heimdall/rules.yaml:ro - ./signer.pem:/etc/heimdall/signer.pem:ro command: serve proxy -c /etc/heimdall/config.yaml --insecure upstream: (2) image: containous/whoami:latest command: - --port=8081 idp: (3) image: nginx:1.25.4 volumes: - ./idp.nginx:/etc/nginx/nginx.conf:ro - ./jwks.json:/var/www/nginx/jwks.json:ro opa: (4) image: openpolicyagent/opa:0.62.1 command: run --server /etc/opa/policies volumes: - ./policy.rego:/etc/opa/policies/policy.rego:ro 1 These lines configure heimdall to use our configuration, key store, and rule file, and to run in proxy operation mode. We’re using the --insecure flag here to simplify our setup, which disables enforcement of some security settings you can learn about more here. 2 Here, we configure the \u0026#34;upstream\u0026#34; service, which, as mentioned earlier, is a simple service that echoes everything it receives. 3 This section configures our NGINX service, which mimics an IDP system and exposes a JWKS endpoint with our key material. 4 These lines configure our OPA instance to use the authorization policy. Alternatively, if you prefer to implement EAA with heimdall, create or modify the following docker-compose-eaa.yaml file. Be sure to update it with the correct paths to the heimdall-config.yaml, upstream-rules.yaml, policy.rego, idp.nginx, and jwks.json files from above.\nservices: proxy: (1) image: traefik:2.11.0 ports: - \u0026#34;9090:9090\u0026#34; command: \u0026gt; --providers.docker=true --providers.docker.exposedbydefault=false --entryPoints.http.address=\u0026#34;:9090\u0026#34; --accesslog --api=true --api.insecure=true volumes: - \u0026#34;/var/run/docker.sock:/var/run/docker.sock:ro\u0026#34; labels: - traefik.enable=true - traefik.http.routers.traefik_http.service=api@internal - traefik.http.routers.traefik_http.entrypoints=http - traefik.http.middlewares.heimdall.forwardauth.address=http://heimdall:4455 (2) - traefik.http.middlewares.heimdall.forwardauth.authResponseHeaders=Authorization heimdall: (3) image: dadrus/heimdall:dev volumes: - ./heimdall-config.yaml:/etc/heimdall/config.yaml:ro - ./upstream-rules.yaml:/etc/heimdall/rules.yaml:ro - ./signer.pem:/etc/heimdall/signer.pem:ro command: serve decision -c /etc/heimdall/config.yaml --insecure upstream: (4) image: containous/whoami:latest command: - --port=8081 labels: - traefik.enable=true - traefik.http.services.whoami.loadbalancer.server.port=8081 - traefik.http.routers.whoami.rule=PathPrefix(\u0026#34;/\u0026#34;) - traefik.http.routers.whoami.middlewares=heimdall idp: (5) image: nginx:1.25.4 volumes: - ./idp.nginx:/etc/nginx/nginx.conf:ro - ./jwks.json:/var/www/nginx/jwks.json:ro opa: (6) image: openpolicyagent/opa:0.62.1 command: run --server /etc/opa/policies volumes: - ./policy.rego:/etc/opa/policies/policy.rego:ro 1 These lines configure Traefik, which is responsible for dispatching incoming requests and forwarding them to heimdall before routing to the target service. We use the ForwardAuth middleware here, which requires additional configuration at the route level. 2 Here we configure Traefik to forward requests to heimdall. 3 These lines configure heimdall to use our configuration, key store, and rule file, and to run in decision operation mode. We’re using the --insecure flag here to simplify our setup, which disables enforcement of some security settings you can learn about more here. 4 Here, we configure the \u0026#34;upstream\u0026#34; service. As previously mentioned, it is a very simple service that just echoes back everything it receives. We also need to provide some route-level configuration here to ensure requests are forwarded to heimdall. While we could have used a global configuration, we decided against it to avoid adding another configuration file. 5 This is our NGINX service, which mimics an IDP system and exposes a JWKS endpoint with our key material. 6 These lines configure our OPA instance to use the authorization policy. Start Environment Open your terminal and start the services in the directory where the docker-compose.yaml file is located:\n$ docker compose up Consume the API Roll up your sleeves. We’re going to play with our setup now. Open a new terminal window and put it nearby the terminal, you started the environment in. This way you’ll see what is going on in the environment when you use it.\nLet’s try the /public endpoint first.\n$ curl 127.0.0.1:9090/public + You should see an output similar to the one shown below:\n+\nHostname: 94e60bba8498 IP: 127.0.0.1 IP: 172.19.0.3 RemoteAddr: 172.19.0.4:53980 GET /public HTTP/1.1 Host: upstream:8081 User-Agent: curl/8.2.1 Accept: */* Accept-Encoding: gzip Forwarded: for=172.19.0.1;host=127.0.0.1:9090;proto=http + That was expected, as we sent a request to our public endpoint.\nNow, let’s try some other endpoints:\n$ curl -v 127.0.0.1:9090/admin + The -v flag is added to the curl command intentionally. Without it, we won’t see the detailed output. With it, you’ll see the response shown below:\n+\n* processing: 127.0.0.1:9090/admin * Trying 127.0.0.1:9090... * Connected to 127.0.0.1 (127.0.0.1) port 9090 \u0026gt; GET /admin HTTP/1.1 \u0026gt; Host: 127.0.0.1:9090 \u0026gt; User-Agent: curl/8.2.1 \u0026gt; Accept: */* \u0026gt; \u0026lt; HTTP/1.1 401 Unauthorized \u0026lt; Date: Wed, 06 Mar 2024 16:14:05 GMT \u0026lt; Content-Length: 0 \u0026lt; * Connection #0 to host 127.0.0.1 left intact + That is, unauthorized. Requests to any endpoint other than /public will result in the same output.\nLet’s now use a valid JWT to access either the /admin or /user endpoint. Here’s a new request to our /admin endpoint, which includes a bearer token in the Authorization header. This should grant us access:\n$ curl -H \u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjUxMDA3NTEsImlhdCI6MTcwOTc0MDc1MSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI0NjExZDM5Yy00MzI1LTRhMWYtYjdkOC1iMmYxMTE3NDEyYzAiLCJuYmYiOjE3MDk3NDA3NTEsInJvbGUiOiJhZG1pbiIsInN1YiI6IjEifQ.mZZ_UqC8RVzEKBPZbPs4eP-MkXLK22Q27ZJ34UwJiioFdaYXqYJ4ZsatP0TbpKeNyF83mkrrCGL_pWLFTho7Gg\u0026#34; 127.0.0.1:9090/admin + Now we can access the endpoint and see the following output:\n+\nHostname: 94e60bba8498 IP: 127.0.0.1 IP: 172.19.0.2 RemoteAddr: 172.19.0.4:43688 GET /admin HTTP/1.1 Host: upstream:8081 User-Agent: curl/8.2.1 Accept: */* Accept-Encoding: gzip Authorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2MzYwMDAsImlhdCI6MTcxODYzNTcwMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiIyZjc0MjRmNy05ZWFkLTQ4MzItYmM2Yy0xM2FiNDY5NTNjOTQiLCJuYmYiOjE3MTg2MzU3MDAsInN1YiI6IjEifQ._xy_TRsQpiBPsdGi6gh1IOlyep62YpgxiqquXhg-guVdhpslS4PfVH139dv50GOX0fj3F31q8__8QWWvzPJCEI0aEaaMazIVZ24qjyFM2LJvX0o0ILePxfeDU3bhzN8i Forwarded: for=172.19.0.1;host=127.0.0.1:9090;proto=http + Take a closer look at the JWT echoed by our service, e.g. by making use of jwt.io. This token has been issued by heimdall, not the one you sent with curl.\nNow, try the same request to the /user endpoint. It will be refused due to the wrong role. Let’s use a different JWT that should grant us access.\n$ curl -H \u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjUxMDA3NTEsImlhdCI6MTcwOTc0MDc1MSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiIzZmFmNDkxOS0wZjUwLTQ3NGItOGExMy0yOTYzMjEzNThlOTMiLCJuYmYiOjE3MDk3NDA3NTEsInJvbGUiOiJ1c2VyIiwic3ViIjoiMiJ9.W5xCpwsFShS0RpOtrm9vrV2dN6K8pRr5gQnt0kluzLE6oNWFzf7Oot-0YLCPa64Z3XPd7cfGcBiSjrzKZSAj4g\u0026#34; 127.0.0.1:9090/user + This should work now. We omitted the output for brevity, but you should see a successful response.\nTry sending requests to the /private endpoint using any of the tokens from above. It will fail, as heimdall will not allow access.\nCleanup Once you’re done, stop the environment with CTRL-C and delete the created files. If you started Docker Compose in the background, tear down the environment with:\n$ docker compose down ","description":"This simple quickstart guide will walk you through the steps to protect an application using heimdall. You'll learn how to configure heimdall as an authentication and authorization proxy in front of your application, as well as how to implement an Edge-level Authorization Architecture (EAA) with heimdall's help.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_overview\"\u003eOverview\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this guide, we’ll configure two setups to protect a service that exposes a few endpoints:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ccode\u003e/public\u003c/code\u003e endpoint is, as the name implies, public. Every request to it should be forwarded as is.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ccode\u003e/user\u003c/code\u003e endpoint should only be accessible to users with the \u003ccode\u003euser\u003c/code\u003e role.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ccode\u003e/admin\u003c/code\u003e endpoint should only be accessible to users with the \u003ccode\u003eadmin\u003c/code\u003e role.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ccode\u003e/private\u003c/code\u003e endpoint, along with any other potentially exposed endpoints, should not be accessible at all. All requests to it should be rejected.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor authentication, we’ll use JWTs containing the respective roles. Authorization will be handled with the help of Open Policy Agent (OPA).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both setups, we’ll create minimal but complete environments using Docker Compose with:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://doc.traefik.io/traefik/\"\u003eTraefik\u003c/a\u003e as the edge proxy,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://hub.docker.com/r/containous/whoami/\"\u003econtainous/whoami\u003c/a\u003e (a service that echoes back everything it receives), mimicking our service exposing the endpoints described above,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ean \u003ca href=\"https://nginx.org/en/\"\u003eNGINX\u003c/a\u003e server serving the public key for verifying the JWTs (mimicking the JWKS endpoint typically exposed by an OIDC provider),\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://www.openpolicyagent.org/\"\u003eOPA\u003c/a\u003e, which evaluates the authorization policy,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eheimdall, orchestrating everything to enforce the above requirements.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis quickstart and others demonstrating different integration options are also available on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples/docker-compose/quickstarts\"\u003eGitHub\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo follow this guide, you’ll need the following tools installed locally:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/install/\"\u003eDocker\u003c/a\u003e,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/compose/install/\"\u003edocker-compose\u003c/a\u003e, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea text editor of your choice.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configure\"\u003eConfigure\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eHeimdall can be configured via environment variables, as well as using a configuration file. For simplicity, we’ll use a configuration file in this guide. Create a file named \u003ccode\u003eheimdall-config.yaml\u003c/code\u003e with the following contents:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edebug\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emetrics\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eserve\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003edecision\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etrusted_proxies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e0.0.0.0/0\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eunauthorized\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_auth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ejwks_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://idp:8080/.well-known/jwks\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003edemo_issuer\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopa\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://opa:8181/v1/data/{{ .Values.policy }}\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e{}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.result == true\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/signer.pem\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e \u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e(9)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003edefault_rule\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e(10)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eproviders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e(11)\u003c/b\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/rules.yaml\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSince heimdall emits logs at the \u003ccode\u003eerror\u003c/code\u003e level by default, and we want to monitor what’s happening, we’ll set the log level to \u003ccode\u003edebug\u003c/code\u003e. This way, we’ll not only see the results of a particular rule execution (which you would see with the \u003ccode\u003einfo\u003c/code\u003e log level), but also detailed logs of what’s going on inside each rule. Additionally, we disable tracing and metrics collection, which are pulled by default to an OTEL agent, to avoid error messages related to the unavailability of the agent. For more information on available observability options, see the \u003ca href=\"/docs/operations/observability/#_logging\"\u003eObservability\u003c/a\u003e chapter.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis configuration instructs heimdall to trust \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers from any source. We need this for integration with Traefik, which uses these headers while forwarding requests to heimdall. The IP address used depends on your local Docker configuration.\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nNever use this in production - always restrict trusted IPs instead! Refer to the documentation on the \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003etrusted_proxies\u003c/a\u003e property and \u003ca href=\"/docs/operations/security/#_http_header_security_considerations\"\u003eSecurity Considerations\u003c/a\u003e for more details.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we define our \u003ca href=\"/docs/mechanisms/catalogue/\"\u003ecatalogue of mechanisms\u003c/a\u003e to be used in \u003ca href=\"/docs/rules/regular_rule/\"\u003eupstream service-specific rules\u003c/a\u003e. In this case, we define authenticators, an authorizer, and finalizers.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese two lines define the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authenticators/#_unauthorized\"\u003eunauthorized\u003c/a\u003e\u003c/code\u003e authenticator named \u003ccode\u003edeny_all\u003c/code\u003e, which rejects all requests.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese two lines define the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authenticators/#_anonymous\"\u003eanonymous\u003c/a\u003e\u003c/code\u003e authenticator named \u003ccode\u003eanon\u003c/code\u003e, which allows any request and creates a subject with the ID set to \u003ccode\u003eanonymous\u003c/code\u003e. You can find more information about the subject and other objects \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003ehere\u003c/a\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis and the following lines define and configure the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authenticators/#_jwt\"\u003ejwt\u003c/a\u003e\u003c/code\u003e authenticator named \u003ccode\u003ejwt_auth\u003c/code\u003e. With this configuration, it will check if a request contains an \u003ccode\u003eAuthorization\u003c/code\u003e header with a bearer token in JWT format and validate it using key material fetched from the JWKS endpoint. It will reject requests without a valid JWT or create a subject with the \u003ccode\u003esub\u003c/code\u003e claim set to the token’s \u003ccode\u003esub\u003c/code\u003e value. All other claims will also be added to the subject’s attributes.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we define and configure a \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authorizers/#_remote\"\u003eremote\u003c/a\u003e\u003c/code\u003e authorizer named \u003ccode\u003eopa\u003c/code\u003e. Note how we allow for the overriding of particular settings, which will be specified below when we define the rules.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe following lines define the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/finalizers/#_jwt\"\u003ejwt\u003c/a\u003e\u003c/code\u003e finalizer. This configuration will generate a JWT from the subject object with standard claims, setting the \u003ccode\u003esub\u003c/code\u003e claim to the subject’s ID. The key material used for signing is pulled from the referenced key store.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e9\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese two lines conclude the definition of our mechanisms catalogue and define the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/finalizers/#_noop\"\u003enoop\u003c/a\u003e\u003c/code\u003e finalizer, which, as the name implies, does nothing.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e10\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWith the mechanisms catalogue in place, we can now define a \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e. This rule will be triggered if no other rule matches the request. It also acts as a \u003ca href=\"/docs/concepts/rules/#_default_rule_inheritance\"\u003ebase\u003c/a\u003e for defining regular (upstream service-specific) rules. This rule defines a secure default \u003ca href=\"/docs/concepts/pipelines/#_authentication_authorization_pipeline\"\u003eauthentication \u0026amp; authorization pipeline\u003c/a\u003e, which denies any request using the \u003ccode\u003edeny_all\u003c/code\u003e authenticator. If overridden by a regular rule, it will create a JWT using the \u003ccode\u003ejwt\u003c/code\u003e finalizer.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e11\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe last few lines configure the \u003ca href=\"/docs/rules/providers/#_filesystem\"\u003e\u003ccode\u003efile_system\u003c/code\u003e\u003c/a\u003e provider, which allows loading regular rules from the file system. The provider is also configured to watch for changes, so you can modify the rules in real time.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a file named \u003ccode\u003esigner.pem\u003c/code\u003e with the following content. This file is our key store with a private key, which you’ll see referenced in the configuration above.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"s\"\u003e-----BEGIN EC PRIVATE KEY-----\u003c/span\u003e\n\u003cspan class=\"s\"\u003eMIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy\u003c/span\u003e\n\u003cspan class=\"s\"\u003e1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI\u003c/span\u003e\n\u003cspan class=\"s\"\u003ezlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X\u003c/span\u003e\n\u003cspan class=\"s\"\u003eXVwR/5tokqFVrFxt/5c1x7VdccF4nNM=\u003c/span\u003e\n\u003cspan class=\"s\"\u003e-----END EC PRIVATE KEY-----\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nDo not use this for purposes beyond this tutorial!\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNow, create a rule file named \u003ccode\u003eupstream-rules.yaml\u003c/code\u003e to implement the authentication and authorization requirements for your service. Copy the following contents into it:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo:public\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/public\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\n\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo:protected\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/:user\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath_params\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003euser\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eglob\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e{user,admin}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_auth\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopa\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epolicy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo/can_access\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;input\u0026#34;: {\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;role\u0026#34;: {{ quote .Subject.Attributes.role }},\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;path\u0026#34;: {{ quote .Request.URL.Path }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis rule matches the \u003ccode\u003e/public\u003c/code\u003e endpoint and forwards the request to our upstream service without performing any verification or transformation.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis rule matches the \u003ccode\u003e/user\u003c/code\u003e and \u003ccode\u003e/admin\u003c/code\u003e endpoints, handling both authentication and authorization steps.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nSince we don’t define a finalizer in the second rule’s pipeline, the default rule’s finalizer is reused. There is no need for additional rules, as the default rule will block requests to any other endpoints.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNow that everything related to heimdall configuration is in place, let’s create a policy that OPA will use. Create a file named \u003ccode\u003epolicy.rego\u003c/code\u003e with the following contents:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"rego\"\u003e\u003cspan class=\"ow\"\u003epackage\u003c/span\u003e \u003cspan class=\"n\"\u003edemo\u003c/span\u003e\n\n\u003cspan class=\"ow\"\u003edefault\u003c/span\u003e \u003cspan class=\"n\"\u003ecan_access\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n\n\u003cspan class=\"n\"\u003ecan_access\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"n\"\u003esplit\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003epath\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)[\u003c/span\u003e\u003cspan class=\"m\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003erole\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, we define our policy \u003ccode\u003ecan_access\u003c/code\u003e within the \u003ccode\u003edemo\u003c/code\u003e package. The policy is straightforward, evaluating to either true or false.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eBy default, the \u003ccode\u003ecan_access\u003c/code\u003e policy evaluates to false.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eIt evaluates to true only when the last path fragment of the request matches the user’s role.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNow, let’s configure NGINX to expose a static endpoint that serves a JWKS document under the \u003ccode\u003e.well-known\u003c/code\u003e path. This will allow heimdall to verify the JWTs we will use. Create a file named \u003ccode\u003eidp.nginx\u003c/code\u003e with the following content:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eworker_processes 1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\nuser nginx\u003cspan class=\"p\"\u003e;\u003c/span\u003e\npid /var/run/nginx.pid\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\nevents \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n worker_connections 1024\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\nhttp \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n keepalive_timeout 65\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n server \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n listen 8080\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n location /.well-known/jwks \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n default_type application/json\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n root /var/www/nginx\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n try_files /jwks.json \u003cspan class=\"o\"\u003e=\u003c/span\u003e404\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition, create a file named \u003ccode\u003ejwks.json\u003c/code\u003e containing the public key needed to verify the tokens we will use.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;keys\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;use\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;sig\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;kty\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;EC\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;kid\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;key-1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;crv\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;P-256\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;alg\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;ES256\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;x\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;cv6F6SgBSNWMZKdApZXSuPD6QPtvQyMpk-iRfZxT-vo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;y\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;C1r3OClUvyDgmDQdvxMdB-ucmZ28b8s4uM4Yg-0BZZ4\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWe will place it in the \u003ccode\u003e/var/www/nginx\u003c/code\u003e folder, as mentioned earlier, when we set up our environment.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNow, let’s configure the environment. To run \u003cstrong\u003eheimdall as a proxy\u003c/strong\u003e, create or modify a \u003ccode\u003edocker-compose.yaml\u003c/code\u003e file. Be sure to update it with the correct paths to your \u003ccode\u003eheimdall-config.yaml\u003c/code\u003e, \u003ccode\u003eupstream-rules.yaml\u003c/code\u003e, \u003ccode\u003epolicy.rego\u003c/code\u003e, \u003ccode\u003eidp.nginx\u003c/code\u003e, and \u003ccode\u003ejwks.json\u003c/code\u003e files created earlier.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edadrus/heimdall:dev\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e9090:4455\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./heimdall-config.yaml:/etc/heimdall/config.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./upstream-rules.yaml:/etc/heimdall/rules.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./signer.pem:/etc/heimdall/signer.pem:ro\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eserve proxy -c /etc/heimdall/config.yaml --insecure\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eupstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003econtainous/whoami:latest\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e--port=8081\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eidp\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enginx:1.25.4\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./idp.nginx:/etc/nginx/nginx.conf:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./jwks.json:/var/www/nginx/jwks.json:ro\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eopa\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenpolicyagent/opa:0.62.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erun --server /etc/opa/policies\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./policy.rego:/etc/opa/policies/policy.rego:ro\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure heimdall to use our configuration, key store, and rule file, and to run in proxy operation mode.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWe’re using the \u003ccode\u003e--insecure\u003c/code\u003e flag here to simplify our setup, which disables enforcement of some security settings you can learn about more \u003ca href=\"/docs/operations/security/#_defaults\"\u003ehere\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we configure the \u0026#34;upstream\u0026#34; service, which, as mentioned earlier, is a simple service that echoes everything it receives.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis section configures our NGINX service, which mimics an IDP system and exposes a JWKS endpoint with our key material.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure our OPA instance to use the authorization policy.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAlternatively, if you prefer to implement \u003cstrong\u003eEAA with heimdall\u003c/strong\u003e, create or modify the following \u003ccode\u003edocker-compose-eaa.yaml\u003c/code\u003e file. Be sure to update it with the correct paths to the \u003ccode\u003eheimdall-config.yaml\u003c/code\u003e, \u003ccode\u003eupstream-rules.yaml\u003c/code\u003e, \u003ccode\u003epolicy.rego\u003c/code\u003e, \u003ccode\u003eidp.nginx\u003c/code\u003e, and \u003ccode\u003ejwks.json\u003c/code\u003e files from above.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eproxy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik:2.11.0\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e9090:9090\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--providers.docker=true\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--providers.docker.exposedbydefault=false\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--entryPoints.http.address=\u0026#34;:9090\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--accesslog --api=true --api.insecure=true\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e/var/run/docker.sock:/var/run/docker.sock:ro\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.enable=true\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.routers.traefik_http.service=api@internal\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.routers.traefik_http.entrypoints=http\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.middlewares.heimdall.forwardauth.address=http://heimdall:4455\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.middlewares.heimdall.forwardauth.authResponseHeaders=Authorization\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edadrus/heimdall:dev\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./heimdall-config.yaml:/etc/heimdall/config.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./upstream-rules.yaml:/etc/heimdall/rules.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./signer.pem:/etc/heimdall/signer.pem:ro\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eserve decision -c /etc/heimdall/config.yaml --insecure\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eupstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003econtainous/whoami:latest\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e--port=8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.enable=true\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.services.whoami.loadbalancer.server.port=8081\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.routers.whoami.rule=PathPrefix(\u0026#34;/\u0026#34;)\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.routers.whoami.middlewares=heimdall\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eidp\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enginx:1.25.4\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./idp.nginx:/etc/nginx/nginx.conf:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./jwks.json:/var/www/nginx/jwks.json:ro\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eopa\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenpolicyagent/opa:0.62.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erun --server /etc/opa/policies\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./policy.rego:/etc/opa/policies/policy.rego:ro\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure Traefik, which is responsible for dispatching incoming requests and forwarding them to heimdall before routing to the target service. We use the ForwardAuth middleware here, which requires additional configuration at the route level.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we configure Traefik to forward requests to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure heimdall to use our configuration, key store, and rule file, and to run in decision operation mode.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWe’re using the \u003ccode\u003e--insecure\u003c/code\u003e flag here to simplify our setup, which disables enforcement of some security settings you can learn about more \u003ca href=\"/docs/operations/security/#_defaults\"\u003ehere\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we configure the \u0026#34;upstream\u0026#34; service. As previously mentioned, it is a very simple service that just echoes back everything it receives. We also need to provide some route-level configuration here to ensure requests are forwarded to heimdall. While we could have used a global configuration, we decided against it to avoid adding another configuration file.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is our NGINX service, which mimics an IDP system and exposes a JWKS endpoint with our key material.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure our OPA instance to use the authorization policy.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_start_environment\"\u003eStart Environment\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOpen your terminal and start the services in the directory where the \u003ccode\u003edocker-compose.yaml\u003c/code\u003e file is located:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003edocker compose up\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_consume_the_api\"\u003eConsume the API\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRoll up your sleeves. We’re going to play with our setup now. Open a new terminal window and put it nearby the terminal, you started the environment in. This way you’ll see what is going on in the environment when you use it.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eLet’s try the \u003ccode\u003e/public\u003c/code\u003e endpoint first.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl 127.0.0.1:9090/public\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nYou should see an output similar to the one shown below:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eHostname: 94e60bba8498\nIP: 127.0.0.1\nIP: 172.19.0.3\nRemoteAddr: 172.19.0.4:53980\nGET /public HTTP/1.1\nHost: upstream:8081\nUser-Agent: curl/8.2.1\nAccept: \u003cspan class=\"k\"\u003e*\u003c/span\u003e/\u003cspan class=\"k\"\u003e*\u003c/span\u003e\nAccept-Encoding: \u003cspan class=\"nb\"\u003egzip\n\u003c/span\u003eForwarded: \u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e172.19.0.1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003ehost\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e127.0.0.1:9090\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003eproto\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttp\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nThat was expected, as we sent a request to our public endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eNow, let’s try some other endpoints:\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl \u003cspan class=\"nt\"\u003e-v\u003c/span\u003e 127.0.0.1:9090/admin\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nThe \u003ccode\u003e-v\u003c/code\u003e flag is added to the curl command intentionally. Without it, we won’t see the detailed output. With it, you’ll see the response shown below:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"k\"\u003e*\u003c/span\u003e processing: 127.0.0.1:9090/admin\n\u003cspan class=\"k\"\u003e*\u003c/span\u003e Trying 127.0.0.1:9090...\n\u003cspan class=\"k\"\u003e*\u003c/span\u003e Connected to 127.0.0.1 \u003cspan class=\"o\"\u003e(\u003c/span\u003e127.0.0.1\u003cspan class=\"o\"\u003e)\u003c/span\u003e port 9090\n\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e GET /admin HTTP/1.1\n\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e Host: 127.0.0.1:9090\n\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e User-Agent: curl/8.2.1\n\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e Accept: \u003cspan class=\"k\"\u003e*\u003c/span\u003e/\u003cspan class=\"k\"\u003e*\u003c/span\u003e\n\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e\n\u0026lt; HTTP/1.1 401 Unauthorized\n\u0026lt; Date: Wed, 06 Mar 2024 16:14:05 GMT\n\u0026lt; Content-Length: 0\n\u0026lt;\n\u003cspan class=\"k\"\u003e*\u003c/span\u003e Connection \u003cspan class=\"c\"\u003e#0 to host 127.0.0.1 left intact\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nThat is, unauthorized. Requests to any endpoint other than \u003ccode\u003e/public\u003c/code\u003e will result in the same output.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eLet’s now use a valid JWT to access either the \u003ccode\u003e/admin\u003c/code\u003e or \u003ccode\u003e/user\u003c/code\u003e endpoint. Here’s a new request to our \u003ccode\u003e/admin\u003c/code\u003e endpoint, which includes a bearer token in the \u003ccode\u003eAuthorization\u003c/code\u003e header. This should grant us access:\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjUxMDA3NTEsImlhdCI6MTcwOTc0MDc1MSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI0NjExZDM5Yy00MzI1LTRhMWYtYjdkOC1iMmYxMTE3NDEyYzAiLCJuYmYiOjE3MDk3NDA3NTEsInJvbGUiOiJhZG1pbiIsInN1YiI6IjEifQ.mZZ_UqC8RVzEKBPZbPs4eP-MkXLK22Q27ZJ34UwJiioFdaYXqYJ4ZsatP0TbpKeNyF83mkrrCGL_pWLFTho7Gg\u0026#34;\u003c/span\u003e 127.0.0.1:9090/admin\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nNow we can access the endpoint and see the following output:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eHostname: 94e60bba8498\nIP: 127.0.0.1\nIP: 172.19.0.2\nRemoteAddr: 172.19.0.4:43688\nGET /admin HTTP/1.1\nHost: upstream:8081\nUser-Agent: curl/8.2.1\nAccept: \u003cspan class=\"k\"\u003e*\u003c/span\u003e/\u003cspan class=\"k\"\u003e*\u003c/span\u003e\nAccept-Encoding: \u003cspan class=\"nb\"\u003egzip\n\u003c/span\u003eAuthorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2MzYwMDAsImlhdCI6MTcxODYzNTcwMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiIyZjc0MjRmNy05ZWFkLTQ4MzItYmM2Yy0xM2FiNDY5NTNjOTQiLCJuYmYiOjE3MTg2MzU3MDAsInN1YiI6IjEifQ._xy_TRsQpiBPsdGi6gh1IOlyep62YpgxiqquXhg-guVdhpslS4PfVH139dv50GOX0fj3F31q8__8QWWvzPJCEI0aEaaMazIVZ24qjyFM2LJvX0o0ILePxfeDU3bhzN8i\nForwarded: \u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e172.19.0.1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003ehost\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e127.0.0.1:9090\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003eproto\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttp\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nTake a closer look at the JWT echoed by our service, e.g. by making use of \u003ca href=\"https://jwt.io\"\u003ejwt.io\u003c/a\u003e. This token has been issued by heimdall, not the one you sent with curl.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eNow, try the same request to the \u003ccode\u003e/user\u003c/code\u003e endpoint. It will be refused due to the wrong role. Let’s use a different JWT that should grant us access.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjUxMDA3NTEsImlhdCI6MTcwOTc0MDc1MSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiIzZmFmNDkxOS0wZjUwLTQ3NGItOGExMy0yOTYzMjEzNThlOTMiLCJuYmYiOjE3MDk3NDA3NTEsInJvbGUiOiJ1c2VyIiwic3ViIjoiMiJ9.W5xCpwsFShS0RpOtrm9vrV2dN6K8pRr5gQnt0kluzLE6oNWFzf7Oot-0YLCPa64Z3XPd7cfGcBiSjrzKZSAj4g\u0026#34;\u003c/span\u003e 127.0.0.1:9090/user\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nThis should work now. We omitted the output for brevity, but you should see a successful response.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eTry sending requests to the \u003ccode\u003e/private\u003c/code\u003e endpoint using any of the tokens from above. It will fail, as heimdall will not allow access.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cleanup\"\u003eCleanup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOnce you’re done, stop the environment with \u003ccode\u003eCTRL-C\u003c/code\u003e and delete the created files. If you started Docker Compose in the background, tear down the environment with:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003edocker compose down\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Getting Started"],"tags":null,"title":"Protect an Application","url":"/docs/getting_started/protect_an_app/"},{"categories":null,"content":" Caddy is a modern web server and reverse proxy known for its automatic HTTPS and simplicity. Heimdall can be integrated with Caddy using the forward_auth directive. If heimdall responds with a 2XX status code, Caddy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\nPrerequisites Integration with Caddy requires heimdall being operated in Decision Operation Mode.\nConfiguration Options Since Caddy offers extensive configuration options and heimdall supports multiple integration methods, you can choose any of the examples below. Each setup ensures heimdall can construct the URL of the protected backend server for rule matching purposes.\nIn most cases, you need to configure heimdall to trust your Caddy instances by setting trusted_proxies. Exceptions are detailed in the sections below.\nForward all information in X-Forwarded-* headers This is the simplest integration method, leveraging the X-Forwarded-Method, X-Forwarded-Proto, X-Forwarded-Host, and X-Forwarded-Uri headers that Caddy automatically sets.\nProper configuration of trusted_proxies is mandatory when using this option to prevent spoofing of the X-Forwarded-* headers. # Caddyfile :9090 { reverse_proxy upstream:8081 forward_auth https://heimdall:4455 { (1) uri / (2) copy_headers Authorization (3) } } 1 Configures Caddy to authenticate requests with heimdall before proxying them to the upstream service. Directives before this line are unrelated to heimdall integration and are included for configuration completeness. 2 Specifies heimdall’s verification endpoint. Here, / is used since all relevant request details are passed via X-Forwarded-* headers. 3 Ensures Caddy forwards the Authorization header set by heimdall to the upstream service. This value depends on your Contextualizers and Finalizers configuration) Forward only the path and query information With this method, X-Forwarded-* headers are not used, relying solely on the standard request data. This means the original request’s HTTP scheme and client IP are not available, but there is no need to configure the trusted_proxies property.\n# Caddyfile :9090 { reverse_proxy upstream:8081 forward_auth https://heimdall:4455 { (1) uri {http.request.uri} (2) method {http.request.method} (3) header_down Host {http.request.hostport} (4) copy_headers Authorization (5) } } 1 As in the previous approach, Caddy is configured to authenticate requests with heimdall before proxying them to the upstream service. Directives before this line are unrelated to heimdall integration and are included for configuration completeness. 2 Specifies heimdall’s verification endpoint. Unlike the previous integration method, the uri is set to the original request URI. 3 Ensures Caddy forwards the request using the same HTTP method as the original request. 4 Sets the Host header to match the original request, making it accessible to Heimdall. 5 Ensures Caddy forwards the Authorization header set by heimdall to the upstream service. This value depends on your Contextualizers and Finalizers configuration. Additional Resources Checkout the examples on GitHub for a working demo.\n","description":"This guide explains how to integrate heimdall with Caddy, an open-source web server and reverse proxy known for its automatic HTTPS and simple configuration.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://caddyserver.com\"\u003eCaddy\u003c/a\u003e is a modern web server and reverse proxy known for its automatic HTTPS and simplicity. Heimdall can be integrated with Caddy using the \u003ca href=\"https://caddyserver.com/docs/caddyfile/directives/forward_auth\"\u003eforward_auth\u003c/a\u003e directive. If heimdall responds with a 2XX status code, Caddy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with Caddy requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration_options\"\u003eConfiguration Options\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince Caddy offers extensive configuration options and heimdall supports multiple integration methods, you can choose any of the examples below. Each setup ensures heimdall can construct the URL of the protected backend server for rule matching purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn most cases, you need to configure heimdall to trust your Caddy instances by setting \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003etrusted_proxies\u003c/a\u003e. Exceptions are detailed in the sections below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_forward_all_information_in_x_forwarded_headers\"\u003eForward all information in \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis is the simplest integration method, leveraging the \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e, and \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e headers that Caddy automatically sets.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nProper configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e is mandatory when using this option to prevent spoofing of the \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode\u003e# Caddyfile\n\n:9090 {\n reverse_proxy upstream:8081\n\n forward_auth https://heimdall:4455 { \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n uri / \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n copy_headers Authorization \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n }\n}\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures Caddy to authenticate requests with heimdall before proxying them to the upstream service. Directives before this line are unrelated to heimdall integration and are included for configuration completeness.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSpecifies heimdall’s verification endpoint. Here, \u003ccode\u003e/\u003c/code\u003e is used since all relevant request details are passed via \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eEnsures Caddy forwards the \u003ccode\u003eAuthorization\u003c/code\u003e header set by heimdall to the upstream service. This value depends on your \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration)\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_forward_only_the_path_and_query_information\"\u003eForward only the path and query information\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith this method, \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers are not used, relying solely on the standard request data. This means the original request’s HTTP scheme and client IP are not available, but there is no need to configure the \u003ccode\u003etrusted_proxies\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode\u003e# Caddyfile\n\n:9090 {\n reverse_proxy upstream:8081\n\n forward_auth https://heimdall:4455 { \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n uri {http.request.uri} \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n method {http.request.method} \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n header_down Host {http.request.hostport} \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n copy_headers Authorization \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n }\n}\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAs in the previous approach, Caddy is configured to authenticate requests with heimdall before proxying them to the upstream service. Directives before this line are unrelated to heimdall integration and are included for configuration completeness.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSpecifies heimdall’s verification endpoint. Unlike the previous integration method, the \u003ccode\u003euri\u003c/code\u003e is set to the original request URI.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eEnsures Caddy forwards the request using the same HTTP method as the original request.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSets the \u003ccode\u003eHost\u003c/code\u003e header to match the original request, making it accessible to Heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eEnsures Caddy forwards the \u003ccode\u003eAuthorization\u003c/code\u003e header set by heimdall to the upstream service. This value depends on your \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCheckout the examples on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e for a working demo.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Caddy Integration","url":"/guides/proxies/caddy/"},{"categories":null,"content":" Overview Pipelines are specified in rules and are used to authenticate and authorize the particular requests, as well as to handle encountered errors.\nAs described in the Discover heimdall chapter and also shown in the diagram below, central aspects of heimdall are upstream specific pipelines, which allow you orchestrating different services to authenticate, enrich and authorize incoming HTTP requests, transform the resulting subject information into a format, or obtain credentials required for the communication with the particular upstream services.\nFigure 1. Authentication \u0026amp; Authorization Pipeline Authentication \u0026amp; Authorization Pipeline Even the figure above shows four steps, these are actually organized in three stages as depicted in the diagram below. Each of these stages is assembled by as many mechanisms (which represent the actual steps), as required to fulfill the corresponding requirements.\nFigure 2. Pipeline Stages Authentication Stage: In that stage you can use any amount of authentication mechanisms, to let heimdall communicate with the actual authentication systems. This can be getting information about the authenticated subject of the request, getting key material to verify the authentication information provided in the request, or perform some other activities related to authentication. This stage is mandatory, which means, at least one authentication mechanism must be specified. If multiple are specified, the subsequent ones are only executed if the previous either fail or were not responsible for the authentication data available with the request.\nAuthorization Stage: In that stage you can make use of any amount of contextualization and authorization mechanisms in any order to fulfill your authorization requirements. Here, you let heimdall communicate with other systems to collect contextual information required for authorization purposes (like e.g. getting the country for the IP, the request came from, retrieving subscription status of your customer, etc), and to perform the actual authorization, e.g. by talking to an Open Policy Agent, OpenFGA, any other type of authorization system, or even let heimdall perform the required checks locally. That stage is optional and is only executed after the successful execution of the authentication stage. The mechanisms specified in it are executed in order of their definition.\nFinalization Stage: In that stage, you can use any amount of finalization mechanisms to complete the pipeline execution and allows you transforming the information collected about the subject in the previous stages into a format expected or required by your upstream service, or even driving specific protocols, e.g. to obtain a token required by the upstream service. That stage is optional and is only executed after the successful execution of the previous stage. The mechanisms specified in it are executed in order of their definition.\nStages are implicit. That is, a pipeline is just a list of mechanisms to be executed in the specified order. That means, all authentication mechanisms must be specified before any contextualization, authorization or finalization mechanisms are specified, with all finalization mechanisms required to be specified at the end. Violation of that rule will let heimdall refuse loading of the particular rule. Error Pipeline Obviously, a mechanism used in the previously described Authentication \u0026amp; Authorization Pipeline may fail. That will result in the execution of the error pipeline, which is basically a list of error handler mechanisms, ranging from a simple error response to the client (which sent the request) to sophisticated ones supporting complex logic and redirects. Mechanisms in this pipeline define conditions under which they are executed. The first mechanism, which condition evaluates to true is executed and other are ignored. If conditions of all mechanisms fail, the default error handler is executed (see also below).\nThe error pipeline is optional. If no error handlers are defined, heimdall will just response with an HTTP response code based on the error raised in the authentication \u0026amp; authorization pipeline.\n","description":"Pipelines let you orchestrate existing authentication and authorization systems via mechanisms.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_overview\"\u003eOverview\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePipelines are specified in \u003ca href=\"/docs/concepts/rules/\"\u003erules\u003c/a\u003e and are used to authenticate and authorize the particular requests, as well as to handle encountered errors.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs described in the \u003ca href=\"/docs/getting_started/discover_heimdall/\"\u003eDiscover heimdall\u003c/a\u003e chapter and also shown in the diagram below, central aspects of heimdall are upstream specific pipelines, which allow you orchestrating different services to authenticate, enrich and authorize incoming HTTP requests, transform the resulting subject information into a format, or obtain credentials required for the communication with the particular upstream services.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_fig_heimdall_request_pipeline\" class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-92616c018b7cc4e879c86947d2cf5d7c.svg\" alt=\"Diagram\" width=\"1290\" height=\"294\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 1. Authentication \u0026amp; Authorization Pipeline\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEven the figure above shows four steps, these are actually organized in three stages as depicted in the diagram below. Each of these stages is assembled by as many \u003ca href=\"/docs/concepts/mechanisms/\"\u003emechanisms\u003c/a\u003e (which represent the actual steps), as required to fulfill the corresponding requirements.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-f2a2cc62dbb0fff1aea173b6d0a9aba7.svg\" alt=\"Diagram\" width=\"1340\" height=\"490\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 2. Pipeline Stages\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eAuthentication Stage:\u003c/strong\u003e In that stage you can use any amount of \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eauthentication\u003c/a\u003e mechanisms, to let heimdall communicate with the actual authentication systems. This can be getting information about the authenticated subject of the request, getting key material to verify the authentication information provided in the request, or perform some other activities related to authentication. This stage is mandatory, which means, at least one authentication mechanism must be specified. If multiple are specified, the subsequent ones are only executed if the previous either fail or were not responsible for the authentication data available with the request.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eAuthorization Stage:\u003c/strong\u003e In that stage you can make use of any amount of \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003econtextualization\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/authorizers/\"\u003eauthorization\u003c/a\u003e mechanisms in any order to fulfill your authorization requirements. Here, you let heimdall communicate with other systems to collect contextual information required for authorization purposes (like e.g. getting the country for the IP, the request came from, retrieving subscription status of your customer, etc), and to perform the actual authorization, e.g. by talking to an Open Policy Agent, OpenFGA, any other type of authorization system, or even let heimdall perform the required checks locally. That stage is optional and is only executed after the successful execution of the authentication stage. The mechanisms specified in it are executed in order of their definition.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eFinalization Stage:\u003c/strong\u003e In that stage, you can use any amount of \u003ca href=\"/docs/mechanisms/finalizers/\"\u003efinalization\u003c/a\u003e mechanisms to complete the pipeline execution and allows you transforming the information collected about the subject in the previous stages into a format expected or required by your upstream service, or even driving specific protocols, e.g. to obtain a token required by the upstream service. That stage is optional and is only executed after the successful execution of the previous stage. The mechanisms specified in it are executed in order of their definition.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nStages are implicit. That is, a pipeline is just a list of mechanisms to be executed in the specified order. That means, all \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eauthentication\u003c/a\u003e mechanisms must be specified before any \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003econtextualization\u003c/a\u003e, \u003ca href=\"/docs/mechanisms/authorizers/\"\u003eauthorization\u003c/a\u003e or \u003ca href=\"/docs/mechanisms/finalizers/\"\u003efinalization\u003c/a\u003e mechanisms are specified, with all \u003ca href=\"/docs/mechanisms/finalizers/\"\u003efinalization\u003c/a\u003e mechanisms required to be specified at the end. Violation of that rule will let heimdall refuse loading of the particular rule.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_error_pipeline\"\u003eError Pipeline\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eObviously, a \u003ca href=\"/docs/concepts/mechanisms/\"\u003emechanism\u003c/a\u003e used in the previously described \u003ca href=\"#_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/a\u003e may fail. That will result in the execution of the error pipeline, which is basically a list of \u003ca href=\"/docs/mechanisms/error_handlers/\"\u003eerror handler\u003c/a\u003e mechanisms, ranging from a simple error response to the client (which sent the request) to sophisticated ones supporting complex logic and redirects. Mechanisms in this pipeline define conditions under which they are executed. The first mechanism, which condition evaluates to true is executed and other are ignored. If conditions of all mechanisms fail, the default error handler is executed (see also below).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe error pipeline is optional. If no error handlers are defined, heimdall will just response with an HTTP response code based on the error raised in the authentication \u0026amp; authorization pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Concepts"],"tags":null,"title":"Pipelines","url":"/docs/concepts/pipelines/"},{"categories":null,"content":" Contour is an ingress controller for Kubernetes, implementing a control plane for Envoy edge and a service proxy.\nPrerequisites Integration with Contour requires heimdall being operated in Decision Operation Mode exposing Envoy’s external authorization GRPC protocol.\nBeing security first ingress controller, Contour enforces TLS for communication between Envoy and any external authorization service. For that reason, heimdall must be configured with an appropriate key material and certificate. Same is actually also true for the http route definition of the actual upstream service. The only exception is when configuring Contour using heimdall as a global external auth service.\nGeneral Configuration The official External Authorization Guide from Contour describes the required steps in great detail. While following it, please make attention to the following details specific to heimdall as described below.\nIf you use cert-manager, ensure the feature gate AdditionalCertificateOutputFormats is set to true. This lets cert-manager creating secrets with a property named tls-combined.pem, combining both the key and the certificate in one object, as also typically provided by any other CA and expected by heimdall.\nWhen you configure the Certificate resource to let cert-manager issue a TLS certificate for heimdall, configure the additionalOutputFormats property with the type CombinedPEM to make use of the aforesaid feature gate and have the tls-combined.pem property set in the resulting secret. Here a small snippet showing the relevant parts:\napiVersion: cert-manager.io/v1 kind: Certificate spec: # ... additionalOutputFormats: - type: CombinedPEM # ... If TLS is enabled, which, as said above, is required for integration with Contour, by default heimdall is configured to support TLS v1.3 only. However, it looks like Contour does not configure Envoy to support TLS v1.3 so that the communication with heimdall happens via TLS v1.2 and below. For that reason you have to configure the main service of heimdall to TLS v1.2 being the minimum supported version. Otherwise, Envoy will not be able communicating with heimdall, resulting in 403 responses for any request. The following snippet shows the relevant parts in the heimdall configuration file:\n# ... serve: tls: # important! see explanations above min_version: TLS1.2 key_store: # path to the pem file with key and certificates path: /certs/tls-combined.pem # ... Ensure heimdall is started in Decision Operation Mode exposing Envoy’s external authorization GRPC protocol (achieved by passing the --envoy-grpc flag while starting heimdall) and the required secret with the TLS key material is available to the heimdall container. The following snippet shows the relevant values configuration if you use helm for installing/updating heimdall:\nextraArgs: - --envoy-grpc deployment: volumes: - name: tls-cert-volume secret: secretName: \u0026lt;name of the corresponding secret\u0026gt; volumeMounts: - name: tls-cert-volume readOnly: true mountPath: /certs Define an ExtensionService as described in the referenced Contour guide for heimdall and also shown below\napiVersion: projectcontour.io/v1alpha1 kind: ExtensionService metadata: namespace: \u0026lt;namespace in which heimdall is installed\u0026gt; name: heimdall-ext-service spec: protocol: h2 services: - name: heimdall port: 4455 The ExtensionService resource definition tells Contour to program Envoy with an upstream cluster directing traffic to heimdall. That way, as also described in the Envoy Integration Guide, Envoy will delegate authentication and authorization to heimdall. If heimdall answers with a 200 OK HTTP code, Envoy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is treated as an error and is returned to the client.\nGlobal Configuration A global configuration allows you to setup a single external authorization configuration for all your virtual hosts (HTTP and HTTPS). The only thing you have to do is to reference the ExtensionService, defined above in your Contour config. This is achieved with the following snippet:\nglobalExtAuth: extensionService: \u0026lt;namespace in which heimdall is installed\u0026gt;/\u0026lt;name of the extention service\u0026gt; failOpen: false responseTimeout: 1s You can now define your Ingress Rules. When using HTTPProxy resources instead, Contour allows overriding or disabling of the external auth service on the route level for HTTPs routes.\nRoute-based Configuration The only way to have route based external auth service configuration in Contour, is the usage of HTTPProxy resource instead of the regular Ingress rules, allowing referencing the ExtensionService. Here an example:\napiVersion: projectcontour.io/v1 kind: HTTPProxy metadata: name: echo-app namespace: quickstarts labels: app.kubernetes.io/name: echo-app spec: virtualhost: fqdn: echo-app.local tls: secretName: echo-app authorization: (1) extensionRef: namespace: heimdall name: heimdall-ext-service routes: - conditions: - prefix: / services: - name: echo-app port: 8080 1 Reference to the ExtensionService. Additional Resources Checkout the examples on GitHub for a working demo.\n","description":"This guide explains how to integrate heimdall with Contour, an open source, high performance ingress controller for Kubernetes.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://projectcontour.io/\"\u003eContour\u003c/a\u003e is an ingress controller for Kubernetes, implementing a control plane for \u003ca href=\"https://www.envoyproxy.io/\"\u003eEnvoy\u003c/a\u003e edge and a service proxy.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with Contour requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e exposing Envoy’s external authorization \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto\"\u003eGRPC protocol\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eBeing security first ingress controller, Contour enforces TLS for communication between Envoy and any external authorization service. For that reason, heimdall must be configured with an appropriate key material and certificate. Same is actually also true for the http route definition of the actual upstream service. The only exception is when configuring Contour using heimdall as a global external auth service.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_general_configuration\"\u003eGeneral Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe official \u003ca href=\"https://projectcontour.io/docs/main/guides/external-authorization/\"\u003eExternal Authorization Guide\u003c/a\u003e from Contour describes the required steps in great detail. While following it, please make attention to the following details specific to heimdall as described below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIf you use \u003ca href=\"https://cert-manager.io/\"\u003ecert-manager\u003c/a\u003e, ensure the feature gate \u003ccode\u003eAdditionalCertificateOutputFormats\u003c/code\u003e is set to \u003ccode\u003etrue\u003c/code\u003e. This lets cert-manager creating secrets with a property named \u003ccode\u003etls-combined.pem\u003c/code\u003e, combining both the key and the certificate in one object, as also typically provided by any other CA and expected by heimdall.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhen you configure the \u003ccode\u003eCertificate\u003c/code\u003e resource to let cert-manager issue a TLS certificate for heimdall, configure the \u003ccode\u003eadditionalOutputFormats\u003c/code\u003e property with the type \u003ccode\u003eCombinedPEM\u003c/code\u003e to make use of the aforesaid feature gate and have the \u003ccode\u003etls-combined.pem\u003c/code\u003e property set in the resulting secret. Here a small snippet showing the relevant parts:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecert-manager.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eCertificate\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# ...\u003c/span\u003e\n \u003cspan class=\"na\"\u003eadditionalOutputFormats\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eCombinedPEM\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# ...\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf TLS is enabled, which, as said above, is required for integration with Contour, by default heimdall is configured to support TLS v1.3 only. However, it looks like Contour does not configure Envoy to support TLS v1.3 so that the communication with heimdall happens via TLS v1.2 and below. For that reason you have to configure the main service of heimdall to TLS v1.2 being the minimum supported version. Otherwise, Envoy will not be able communicating with heimdall, resulting in \u003ccode\u003e403\u003c/code\u003e responses for any request. The following snippet shows the relevant parts in the heimdall configuration file:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# ...\u003c/span\u003e\n\u003cspan class=\"na\"\u003eserve\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# important! see explanations above\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# path to the pem file with key and certificates\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/certs/tls-combined.pem\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# ...\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eEnsure heimdall is started in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e exposing Envoy’s external authorization \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto\"\u003eGRPC protocol\u003c/a\u003e (achieved by passing the \u003ccode\u003e--envoy-grpc\u003c/code\u003e flag while starting heimdall) and the required secret with the TLS key material is available to the heimdall container. The following snippet shows the relevant values configuration if you use helm for installing/updating heimdall:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eextraArgs\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e--envoy-grpc\u003c/span\u003e\n\u003cspan class=\"na\"\u003edeployment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etls-cert-volume\u003c/span\u003e\n \u003cspan class=\"na\"\u003esecret\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esecretName\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;name of the corresponding secret\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumeMounts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etls-cert-volume\u003c/span\u003e\n \u003cspan class=\"na\"\u003ereadOnly\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003emountPath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/certs\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDefine an \u003ca href=\"https://projectcontour.io/docs/1.25/config/api/#projectcontour.io/v1alpha1.ExtensionService\"\u003e\u003ccode\u003eExtensionService\u003c/code\u003e\u003c/a\u003e as described in the referenced Contour guide for heimdall and also shown below\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eprojectcontour.io/v1alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eExtensionService\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;namespace in which heimdall is installed\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-ext-service\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprotocol\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eh2\u003c/span\u003e\n \u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e4455\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ccode\u003eExtensionService\u003c/code\u003e resource definition tells Contour to program Envoy with an upstream cluster directing traffic to heimdall. That way, as also described in the \u003ca href=\"/guides/proxies/envoy/\"\u003eEnvoy Integration Guide\u003c/a\u003e, Envoy will delegate authentication and authorization to heimdall. If heimdall answers with a \u003ccode\u003e200 OK\u003c/code\u003e HTTP code, Envoy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is treated as an error and is returned to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA global configuration allows you to setup a single external authorization configuration for all your virtual hosts (HTTP and HTTPS). The only thing you have to do is to reference the \u003ccode\u003eExtensionService\u003c/code\u003e, defined above in your Contour config. This is achieved with the following snippet:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eglobalExtAuth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eextensionService\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;namespace in which heimdall is installed\u0026gt;/\u0026lt;name of the extention service\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003efailOpen\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"na\"\u003eresponseTimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can now define your \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/ingress/#the-ingress-resource\"\u003eIngress Rules\u003c/a\u003e. When using \u003ca href=\"https://projectcontour.io/docs/1.25/config/api/#projectcontour.io/v1.HTTPProxy\"\u003e\u003ccode\u003eHTTPProxy\u003c/code\u003e\u003c/a\u003e resources instead, Contour allows overriding or disabling of the external auth service on the route level for HTTPs routes.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_route_based_configuration\"\u003eRoute-based Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe only way to have route based external auth service configuration in Contour, is the usage of \u003ca href=\"https://projectcontour.io/docs/1.25/config/api/#projectcontour.io/v1.HTTPProxy\"\u003e\u003ccode\u003eHTTPProxy\u003c/code\u003e\u003c/a\u003e resource instead of the regular Ingress rules, allowing referencing the \u003ccode\u003eExtensionService\u003c/code\u003e. Here an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eprojectcontour.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eHTTPProxy\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eecho-app\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003equickstarts\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eecho-app\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evirtualhost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efqdn\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eecho-app.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esecretName\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eecho-app\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eextensionRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-ext-service\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econditions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/\u003c/span\u003e\n \u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eecho-app\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e8080\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eReference to the \u003ccode\u003eExtensionService\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCheckout the examples on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e for a working demo.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Contour Integration","url":"/guides/proxies/contour/"},{"categories":null,"content":" Mechanism Categories All supported mechanisms fall into the following five categories, each implementing different mechanisms types (addressing different protocols or scenarios):\nAuthenticators, which inspect HTTP requests for presence of authentication objects, like e.g. the presence of a specific cookie. If such objects exist, authenticators verify the related authentication status and obtain information about the corresponding subject. A subject, could be a user who tries to use particular functionality of the upstream service, a machine (if you have machine-2-machine interaction), or something different. Authenticators ensure the subject is authenticated and the information available about it is valid.\nAuthorizers, which ensure that the subject obtained via an authenticator has the required permissions to submit the given HTTP request and thus to execute the corresponding logic in the upstream service. E.g. a specific endpoint of the upstream service might only be accessible to a \u0026#34;user\u0026#34; from the \u0026#34;admin\u0026#34; group, or to an HTTP request if a specific HTTP header is set.\nContextualizers, which enrich the information about the subject obtained via an authenticator with further contextual information, required either by the upstream service itself or an authorizer. This can be handy if the actual authentication system doesn’t have all information about the subject (which is usually the case in microservice architectures), or if dynamic information about the subject, like the current location based on the IP address, is required.\nFinalizers, which, as the name implies, finalize the execution of the pipeline and enrich the request with data such as subject information or authentication tokens required by the upstream service. The available options range from doing nothing, adding a simple header over a structured JWT, to driving specific protocols, e.g. to obtain a token required by the upstream service.\nError Handlers, which are responsible for execution of logic if any of the mechanisms described above fail. These range from a simple error response to the client, which sent the request, to sophisticated ones, supporting complex logic and redirects.\nAll mechanisms are stateless. Even some of them support caching, the corresponding data is not stored on the mechanisms level. A cache backend is used instead, defaulting to an in-memory key-value store. Mechanisms Catalogue Those mechanisms, which should be available for usage in rules, must be defined/configured first. That suits the following purposes:\nMechanisms are per se generic and must be configured for usage in particular use cases.\nThat configuration provides useful default behavior addressing your particular requirements, like which identity management system to use, etc.\nOnly those mechanisms, which are defined can be used in rules. With other words, if you do not define any mechanism, you cannot define any rule.\nThat makes the definition of rules also very simple - just reference the required mechanisms and \u0026#34;tune\u0026#34; the configuration, specified in the catalogue only if required. Not everything can be tuned though.\nIt also provides secure defaults. E.g. that way you can ensure heimdall communicates only to those systems, you allowed.\n","description":"Mechanisms are the building blocks for rule specific pipelines and define the required behavior for these.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_mechanism_categories\"\u003eMechanism Categories\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll supported mechanisms fall into the following five categories, each implementing different mechanisms types (addressing different protocols or scenarios):\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"/docs/mechanisms/authenticators/\"\u003eAuthenticators\u003c/a\u003e, which inspect HTTP requests for presence of authentication objects, like e.g. the presence of a specific cookie. If such objects exist, authenticators verify the related authentication status and obtain information about the corresponding subject. A subject, could be a user who tries to use particular functionality of the upstream service, a machine (if you have machine-2-machine interaction), or something different. Authenticators ensure the subject is authenticated and the information available about it is valid.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"/docs/mechanisms/authorizers/\"\u003eAuthorizers\u003c/a\u003e, which ensure that the subject obtained via an authenticator has the required permissions to submit the given HTTP request and thus to execute the corresponding logic in the upstream service. E.g. a specific endpoint of the upstream service might only be accessible to a \u0026#34;user\u0026#34; from the \u0026#34;admin\u0026#34; group, or to an HTTP request if a specific HTTP header is set.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e, which enrich the information about the subject obtained via an authenticator with further contextual information, required either by the upstream service itself or an authorizer. This can be handy if the actual authentication system doesn’t have all information about the subject (which is usually the case in microservice architectures), or if dynamic information about the subject, like the current location based on the IP address, is required.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e, which, as the name implies, finalize the execution of the pipeline and enrich the request with data such as subject information or authentication tokens required by the upstream service. The available options range from doing nothing, adding a simple header over a structured JWT, to driving specific protocols, e.g. to obtain a token required by the upstream service.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"/docs/mechanisms/error_handlers/\"\u003eError Handlers\u003c/a\u003e, which are responsible for execution of logic if any of the mechanisms described above fail. These range from a simple error response to the client, which sent the request, to sophisticated ones, supporting complex logic and redirects.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAll mechanisms are stateless. Even some of them support caching, the corresponding data is not stored on the mechanisms level. A \u003ca href=\"/docs/operations/cache/\"\u003ecache backend\u003c/a\u003e is used instead, defaulting to an in-memory key-value store.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_mechanisms_catalogue\"\u003eMechanisms Catalogue\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThose mechanisms, which should be available for usage in rules, must be defined/configured first. That suits the following purposes:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eMechanisms are per se generic and must be configured for usage in particular use cases.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThat configuration provides useful default behavior addressing your particular requirements, like which identity management system to use, etc.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOnly those mechanisms, which are defined can be used in rules. With other words, if you do not define any mechanism, you cannot define any rule.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThat makes the definition of rules also very simple - just reference the required mechanisms and \u0026#34;tune\u0026#34; the configuration, specified in the catalogue only if required. Not everything can be tuned though.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIt also provides secure defaults. E.g. that way you can ensure heimdall communicates only to those systems, you allowed.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Concepts"],"tags":null,"title":"Mechanisms ","url":"/docs/concepts/mechanisms/"},{"categories":null,"content":" Emissary-Ingress is an Envoy-powered open source, high performance ingress controller and API Gateway for Kubernetes from Ambassador Labs. Integration happens by letting Emissary-Ingress delegating authentication and authorization to heimdall. If heimdall answers with a 2XX code, the ingress controller will grant access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\nPrerequisites Integration with Emissary-Ingress requires heimdall being operated in Decision Operation Mode.\nGlobal Configuration Integration with Emissary-Ingress can be achieved either\nby creating an AuthService resource for heimdall, or\nby creating an External Filter if you’re using the commercial Ambassador Edge Stack.\nIn both cases the underlying Envoy proxy will be configured to delegate authentication and authorization of all incoming requests for all routes to heimdall. The code snippet below shows the corresponding AuthService resource which configures Emissary Ingress to let Envoy communicate over the GRPC protocol with heimdall.\napiVersion: getambassador.io/v3alpha1 kind: AuthService metadata: name: heimdall namespace: heimdall spec: auth_service: \u0026#34;https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34; (1) proto: grpc protocol_version: v3 (2) 1 Configures the controller to use heimdall’s main service endpoint with \u0026lt;heimdall service name\u0026gt;, \u0026lt;namespace\u0026gt; and \u0026lt;port\u0026gt; depending on your configuration. If heimdall is not operated in the same namespace as the ingress controller, it is important to configure the full DNS, otherwise Envoy will not be able to resolve the IP of heimdall. 2 Sets the used Envoy’s ExtAuth GRPC protocol version to v3, as this is the only version supported by heimdall. If not set, Emissary will default to v2. The integration option shown above requires usage of the --envoy-grpc flag when starting heimdall. Unlike e.g. Contour, Emissary-Ingress allows however the usage of both, the Envoy’s external authorization GRPC protocol (used here), and the plain HTTP protocol. Route-Level configuration The single available configuration option on route level only supports disabling of request forwarding. That can be achieved by configuring a Mapping resource and setting bypass_auth to true (see also Bypass authentication).\nAdditional Resources Checkout the examples on GitHub for a working demo.\n","description":"This guide explains how to integrate heimdall with Emissary-Ingress Controller.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://www.getambassador.io/products/api-gateway\"\u003eEmissary-Ingress\u003c/a\u003e is an Envoy-powered open source, high performance ingress controller and API Gateway for Kubernetes from \u003ca href=\"https://www.getambassador.io/\"\u003eAmbassador Labs\u003c/a\u003e. Integration happens by letting Emissary-Ingress delegating authentication and authorization to heimdall. If heimdall answers with a 2XX code, the ingress controller will grant access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with Emissary-Ingress requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIntegration with Emissary-Ingress can be achieved either\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eby creating an \u003ca href=\"https://www.getambassador.io/docs/emissary/latest/topics/running/services/auth-service\"\u003e\u003ccode\u003eAuthService\u003c/code\u003e\u003c/a\u003e resource for heimdall, or\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eby creating an \u003ca href=\"https://www.getambassador.io/docs/edge-stack/latest/topics/using/filters/external\"\u003eExternal Filter\u003c/a\u003e if you’re using the commercial \u003ca href=\"https://www.getambassador.io/docs/edge-stack\"\u003eAmbassador Edge Stack\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both cases the underlying Envoy proxy will be configured to delegate authentication and authorization of all incoming requests for all routes to heimdall. The code snippet below shows the corresponding \u003ccode\u003eAuthService\u003c/code\u003e resource which configures Emissary Ingress to let Envoy communicate over the GRPC protocol with heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egetambassador.io/v3alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthService\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_service\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://\u0026lt;heimdall\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eservice\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eproto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egrpc\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprotocol_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ev3\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures the controller to use heimdall’s main service endpoint with \u003ccode\u003e\u0026lt;heimdall service name\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;namespace\u0026gt;\u003c/code\u003e and \u003ccode\u003e\u0026lt;port\u0026gt;\u003c/code\u003e depending on your configuration. If heimdall is not operated in the same namespace as the ingress controller, it is important to configure the full DNS, otherwise Envoy will not be able to resolve the IP of heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSets the used Envoy’s ExtAuth GRPC protocol version to v3, as this is the only version supported by heimdall. If not set, Emissary will default to v2.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe integration option shown above requires usage of the \u003ccode\u003e--envoy-grpc\u003c/code\u003e flag when starting heimdall. Unlike e.g. Contour, Emissary-Ingress allows however the usage of both, the \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto\"\u003eEnvoy’s external authorization GRPC\u003c/a\u003e protocol (used here), and the plain HTTP protocol.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_route_level_configuration\"\u003eRoute-Level configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe single available configuration option on route level only supports disabling of request forwarding. That can be achieved by configuring a \u003ca href=\"https://www.getambassador.io/docs/edge-stack/latest/topics/using/intro-mappings#introduction-to-the-mapping-resource\"\u003e\u003ccode\u003eMapping\u003c/code\u003e\u003c/a\u003e resource and setting \u003ccode\u003ebypass_auth\u003c/code\u003e to \u003ccode\u003etrue\u003c/code\u003e (see also \u003ca href=\"https://www.getambassador.io/docs/edge-stack/latest/topics/using/authservice#bypass-authentication\"\u003eBypass authentication\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCheckout the examples on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e for a working demo.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Emissary Ingress Integration","url":"/guides/proxies/emissary/"},{"categories":null,"content":" You can compare the relation between mechanisms and rules to a relation between a catalogue at a car dealer and a real car, when you get it. So, mechanisms is what you can see and select in a catalogue (though, in case of heimdall you have to define that catalogue first) to compile your car and the rule is your car with real components and behaviour. In that sense when you define a rule, you specify which mechanisms should it be built from and whether you would like some \u0026#34;tuning\u0026#34; to be applied to better suit your needs.\nRule Types Heimdall supports two types of rules:\nThe upstream specific rule, also called the regular rule. You can define as many regular rules, as required. These rules are dynamic by nature and can come and go together with the upstream service defining these.\nThe default rule, which, if defined, is used by the regular rules to inherit their behaviour and is also executed if no other rule matches.\nMemory Footprint Even the first paragraphs compare mechanisms and the rules with a catalogue of car parts and a real car, things are a bit more complex in reality.\nTo minimize the memory footprint, heimdall instanciates all defined mechanisms on start up. And since all mechanisms are stateless, following is happening at runtime, when the rule is loaded:\nIf a rule, respectively its pipeline just references a mechanism without providing additional configuration, the already instantiated mechanism is used.\nOtherwise, if the pipeline overrides any parts of the default mechanism configuration, a shallow copy of the referenced mechanism instance (created at start up) is created, and only those parts, which differ are replaced with new objects, representing the pipeline specific configuration.\nExecution of Rules The diagram below sketches the logic executed by heimdall for each and every incoming request.\nAny rule matching request? - This is the first step executed by heimdall in which it tries to find a matching rule. If there is no matching rule, heimdall either falls back to the default rule if available, or the request is denied. Otherwise, the rule specific authentication \u0026amp; authorization pipeline is executed.\nExecute authentication \u0026amp; authorization pipeline - when a rule is matched, the mechanisms defined in its authentication \u0026amp; authorization pipeline are executed.\nForward request, respectively respond to the API gateway - when the above steps succeed, heimdall, depending on the operating mode, responds with, respectively forwards whatever was defined in the pipeline (usually this is a set of HTTP headers). Otherwise\nExecute error pipeline is executed if any of the mechanisms, defined in the authentiction \u0026amp; authorization pipeline fail. This again results in a response, this time however, based on the definition in the used error handler.\nMatching of Rules As written above, an upstream specific rule is only executed when it matches an incoming request.\nThe actual matching happens via the requests URL path, which is guaranteed to happen with O(log(n)) time complexity and is based on the path expressions specified in the loaded rules. These expressions support usage of (named) wildcards to capture segments of the matched path. The implementation ensures, that more specific path expressions are matched first regardless of the placement of rules in a rule set.\nAdditional conditions, like the host, the HTTP method, or application of regular or glob expressions can also be taken into account, allowing different rules for the same path expressions. The information about the HTTP method, scheme, host, path and query is taken either from the request itself, or if present and allowed, from the X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Uri and X-Forwarded-Method headers of the incoming request.\nThere is also an option to have backtracking to a rule with a less specific path expression, if the actual specific path is matched, but the above said additional conditions are not satisfied.\nDefault Rule \u0026amp; Inheritance The Rule Types section tells, that a default rule can be used as a base to inherit behavior for the regular rule.\nIn principle, there is a need to differentiate two things:\nthe defined rule, which is what you define\nthe effective rule, which is what is executed at runtime\nThis is comparable to the polymorphism concept in programming languages. So, how does it work?\nImagine, the concept of a rule is e.g. an interface written in Java defining the following methods:\npublic interface Rule { public void executeAuthenticationStage(req Request) public void executeAuthorizationStage(req Request) public void executeFinalizationStage(req Request) public void handleError(req Request) } And the logic described in Execution of Rules is implemented similar to what is shown in the snippet below\nRule rule = findMatchingRule(req) if (rule == null) { throw new NotFoundError() } try { // execution of the authentication \u0026amp; authorization pipeline rule.executeAuthenticationStage(req) rule.executeAuthorizationStage(req) rule.executeFinalizationStage(req) // further logic related to response creation } catch(Exception e) { // execution of the error pipeline rule.handleError(req) // further logic related to response creation } with findMatchingRule returning a specific instance of a class implementing our Rule interface matching the request.\nSince there is some default behaviour in place, like error handling, if the error pipeline is empty, and some stages of the authentication \u0026amp; authorization pipeline is optional, internally, there is some kind of base rule in place, all other rules inherit from. So something like shown in the snippet below.\npublic abstract class BaseRule implements Rule { public abstract void executeAuthenticationStage(req Request) public void executeAuthorizationStage(req Request) {} public void executeFinalizationStage(req Request) {} public void handleError(req Request) { handlerErrorDefault(req) } } If there is no default rule configured, an upstream specific rule can then be considered as a class inheriting from that BaseRule and must implement at least the executeAuthenticationStage method, similar to what is shown below\npublic class MySpecificRule extends BaseRule { public void executeAuthenticationStage(req Request) { ... } } If however, there is a default rule configured, on one hand, it can be considered as yet another class deriving from our BaseClass. So, something like\npublic class DefaultRule extends BaseRule { public void executeAuthenticationStage(req Request) { ... } public void executeAuthorizationStage(req Request) { ... } public void executeFinalizationStage(req Request) { ... } public void handleError(req Request) { ... } } with at least the aforesaid executeAuthenticationStage method being implemented, as this is also required for the regular rule.\nOn the other hand, the definition of a regular, respectively upstream specific rule is then not a class deriving from the BaseRule, but from the DefaultRule. That way, upstream specific rules are only required, if the behavior of the default rule would not fit the given requirements of a particular service, respectively endpoint. So, if e.g. a rule requires only the authentication stage to be different from the default rule, you would only specify the required authentication mechanisms. That would result in something like shown in the snippet below.\npublic class SpecificRule extends DefaultRule { public void executeAuthenticationStage(req Request) { ... } } And if there is a need to have the authorization stage deviating from the default rule, you would only specify the required authorization and contextualization mechanisms, resulting in something like\npublic class SpecificRule extends DefaultRule { public void executeAuthorizationStage(req Request) { ... } } You cannot override a single mechanism of a particular stage. As soon as you define a single mechanism in a pipeline, belonging to the one or the other stage, the entire stage is overridden. ","description":"Rules defines what should happen to particular requests and under which conditions. They assemble the authentication \u0026 authorization and error pipelines and bring previously configured mechanisms to life.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can compare the relation between mechanisms and rules to a relation between a catalogue at a car dealer and a real car, when you get it. So, mechanisms is what you can see and select in a catalogue (though, in case of heimdall you have to define that catalogue first) to compile your car and the rule is your car with real components and behaviour. In that sense when you define a rule, you specify which mechanisms should it be built from and whether you would like some \u0026#34;tuning\u0026#34; to be applied to better suit your needs.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_rule_types\"\u003eRule Types\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall supports two types of rules:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ca href=\"/docs/rules/regular_rule/\"\u003eupstream specific rule\u003c/a\u003e, also called the regular rule. You can define as many regular rules, as required. These rules are dynamic by nature and can come and go together with the upstream service defining these.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ca href=\"/docs/rules/regular_rule/\"\u003edefault rule\u003c/a\u003e, which, if defined, is used by the regular rules to inherit their behaviour and is also executed if no other rule matches.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_memory_footprint\"\u003eMemory Footprint\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEven the first paragraphs compare mechanisms and the rules with a catalogue of car parts and a real car, things are a bit more complex in reality.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo minimize the memory footprint, heimdall instanciates all defined mechanisms on start up. And since all mechanisms are stateless, following is happening at runtime, when the rule is loaded:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIf a rule, respectively its pipeline just references a mechanism without providing additional configuration, the already instantiated mechanism is used.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOtherwise, if the pipeline overrides any parts of the default mechanism configuration, a shallow copy of the referenced mechanism instance (created at start up) is created, and only those parts, which differ are replaced with new objects, representing the pipeline specific configuration.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_execution_of_rules\"\u003eExecution of Rules\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe diagram below sketches the logic executed by heimdall for each and every incoming request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-95b0331829cfd516daf370f547944674.svg\" alt=\"Diagram\" width=\"820\" height=\"546\"/\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eAny rule matching request?\u003c/strong\u003e - This is the first step executed by heimdall in which it tries to find a \u003ca href=\"#_matching_of_rules\"\u003ematching rule\u003c/a\u003e. If there is no matching rule, heimdall either falls back to the default rule if available, or the request is denied. Otherwise, the rule specific authentication \u0026amp; authorization pipeline is executed.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eExecute authentication \u0026amp; authorization pipeline\u003c/strong\u003e - when a rule is matched, the mechanisms defined in its authentication \u0026amp; authorization pipeline are executed.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eForward request, respectively respond to the API gateway\u003c/strong\u003e - when the above steps succeed, heimdall, depending on the \u003ca href=\"/docs/concepts/operating_modes/\"\u003eoperating mode\u003c/a\u003e, responds with, respectively forwards whatever was defined in the pipeline (usually this is a set of HTTP headers). Otherwise\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eExecute error pipeline\u003c/strong\u003e is executed if any of the mechanisms, defined in the authentiction \u0026amp; authorization pipeline fail. This again results in a response, this time however, based on the definition in the used error handler.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_matching_of_rules\"\u003eMatching of Rules\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs written above, an \u003ca href=\"/docs/rules/regular_rule/\"\u003eupstream specific rule\u003c/a\u003e is only executed when it matches an incoming request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual matching happens via the requests URL path, which is guaranteed to happen with O(log(n)) time complexity and is based on the path expressions specified in the loaded rules. These expressions support usage of (named) wildcards to capture segments of the matched path. The implementation ensures, that more specific path expressions are matched first regardless of the placement of rules in a \u003ca href=\"/docs/concepts/provider/#_rule_sets\"\u003erule set\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAdditional conditions, like the host, the HTTP method, or application of regular or glob expressions can also be taken into account, allowing different rules for the same path expressions. The information about the HTTP method, scheme, host, path and query is taken either from the request itself, or if present and allowed, from the \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e and \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e headers of the incoming request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere is also an option to have backtracking to a rule with a less specific path expression, if the actual specific path is matched, but the above said additional conditions are not satisfied.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_default_rule_inheritance\"\u003eDefault Rule \u0026amp; Inheritance\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"#_rule_types\"\u003eRule Types\u003c/a\u003e section tells, that a default rule can be used as a base to inherit behavior for the regular rule.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn principle, there is a need to differentiate two things:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ethe defined rule, which is what you define\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe effective rule, which is what is executed at runtime\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis is comparable to the polymorphism concept in programming languages. So, how does it work?\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine, the concept of a rule is e.g. an interface written in Java defining the following methods:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003einterface\u003c/span\u003e \u003cspan class=\"nc\"\u003eRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthorizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteFinalizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003ehandleError\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAnd the logic described in \u003ca href=\"#_execution_of_rules\"\u003eExecution of Rules\u003c/a\u003e is implemented similar to what is shown in the snippet below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"nc\"\u003eRule\u003c/span\u003e \u003cspan class=\"n\"\u003erule\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003efindMatchingRule\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n\u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003erule\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nf\"\u003eNotFoundError\u003c/span\u003e\u003cspan class=\"o\"\u003e()\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"k\"\u003etry\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e// execution of the authentication \u0026amp; authorization pipeline\u003c/span\u003e\n \u003cspan class=\"n\"\u003erule\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"n\"\u003erule\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003eexecuteAuthorizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"n\"\u003erule\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003eexecuteFinalizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n\n \u003cspan class=\"c1\"\u003e// further logic related to response creation\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003ecatch\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"nc\"\u003eException\u003c/span\u003e \u003cspan class=\"n\"\u003ee\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e// execution of the error pipeline\u003c/span\u003e\n \u003cspan class=\"n\"\u003erule\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003ehandleError\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n\n \u003cspan class=\"c1\"\u003e// further logic related to response creation\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ewith \u003ccode\u003efindMatchingRule\u003c/code\u003e returning a specific instance of a class implementing our \u003ccode\u003eRule\u003c/code\u003e interface matching the request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince there is some default behaviour in place, like error handling, if the error pipeline is empty, and some stages of the authentication \u0026amp; authorization pipeline is optional, internally, there is some kind of base rule in place, all other rules inherit from. So something like shown in the snippet below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eabstract\u003c/span\u003e \u003cspan class=\"kd\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eBaseRule\u003c/span\u003e \u003cspan class=\"kd\"\u003eimplements\u003c/span\u003e \u003cspan class=\"nc\"\u003eRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eabstract\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthorizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{}\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteFinalizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{}\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003ehandleError\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"n\"\u003ehandlerErrorDefault\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf there is no default rule configured, an upstream specific rule can then be considered as a class inheriting from that \u003ccode\u003eBaseRule\u003c/code\u003e and must implement at least the \u003ccode\u003eexecuteAuthenticationStage\u003c/code\u003e method, similar to what is shown below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eMySpecificRule\u003c/span\u003e \u003cspan class=\"kd\"\u003eextends\u003c/span\u003e \u003cspan class=\"nc\"\u003eBaseRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf however, there is a default rule configured, on one hand, it can be considered as yet another class deriving from our \u003ccode\u003eBaseClass\u003c/code\u003e. So, something like\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eDefaultRule\u003c/span\u003e \u003cspan class=\"kd\"\u003eextends\u003c/span\u003e \u003cspan class=\"nc\"\u003eBaseRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthorizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteFinalizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003ehandleError\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ewith at least the aforesaid \u003ccode\u003eexecuteAuthenticationStage\u003c/code\u003e method being implemented, as this is also required for the regular rule.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOn the other hand, the definition of a regular, respectively upstream specific rule is then not a class deriving from the \u003ccode\u003eBaseRule\u003c/code\u003e, but from the \u003ccode\u003eDefaultRule\u003c/code\u003e. That way, upstream specific rules are only required, if the behavior of the default rule would not fit the given requirements of a particular service, respectively endpoint. So, if e.g. a rule requires only the authentication stage to be different from the default rule, you would only specify the required authentication mechanisms. That would result in something like shown in the snippet below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eSpecificRule\u003c/span\u003e \u003cspan class=\"kd\"\u003eextends\u003c/span\u003e \u003cspan class=\"nc\"\u003eDefaultRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAnd if there is a need to have the authorization stage deviating from the default rule, you would only specify the required authorization and contextualization mechanisms, resulting in something like\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eSpecificRule\u003c/span\u003e \u003cspan class=\"kd\"\u003eextends\u003c/span\u003e \u003cspan class=\"nc\"\u003eDefaultRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthorizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nYou cannot override a single mechanism of a particular stage. As soon as you define a single mechanism in a pipeline, belonging to the one or the other stage, the entire stage is overridden.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Concepts"],"tags":null,"title":"Rules ","url":"/docs/concepts/rules/"},{"categories":null,"content":" Envoy is a high performance distributed proxy designed for single services and applications, as well as a communication bus and “universal data plane” designed for large microservice “service mesh” architectures.\nPrerequisites Integration with Envoy proxy requires heimdall being operated in Decision Operation Mode.\nIntegration Options Envoy makes integration with external authorization services, like heimdall possible via an External Authorization filter in two ways\neither via HTTP\nor via GRPC\nIn both cases, the filter calls an external gRPC or HTTP service to check whether an incoming HTTP request is authorized or not. If the request is deemed unauthorized, then the request will be denied normally with 403 (Forbidden) response.\nEven envoy allows the authorization service sending additional custom metadata to the upstream when GRPC is used, heimdall does not make use of this option. Global Configuration To integrate heimdall with Envoy globally, you need to configure two things:\na cluster entry referencing the actual heimdall address, and\nthe aforesaid filter in the http filter chain\nThe following snippet provides an example on how to create a cluster instance referencing heimdall. It assumes, you have just one heimdall instance deployed, which is also available via heimdall DNS name.\nclusters: # other cluster entries - name: ext-authz (1) type: strict_dns typed_extension_protocol_options: (2) envoy.extensions.upstreams.http.v3.HttpProtocolOptions: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions\u0026#34; explicit_http_config: http2_protocol_options: {} load_assignment: (3) cluster_name: ext-authz endpoints: - lb_endpoints: - endpoint: address: socket_address: address: heimdall port_value: 4455 # other cluster entries 1 The name of our cluster 2 Here, we configure envoy to communicate with heimdall by making use of HTTP 2. This configuration is only required if you want to integrate heimdall via Envoy’s grpc_service (see below), as otherwise envoy will use HTTP 1 for GRPC communication, which is actually not allowed by GRPC (only HTTP 2 is supported). 3 The endpoints in the cluster. In this example, only one endpoint is configured. You can now include an External Authorization HTTP filter in the definition of the HTTP connection manager and depending on the used configuration, either configure the http_service and let it contain the required header name(s), heimdall sets in the HTTP responses (depends on your Contextualizers and Finalizers configuration), or configure the grpc_service.\nUsing HTTP protocol The following snipped shows, how an External Authorization can be defined using http_service to let Envoy communicating with heimdall by making use of the previously defined cluster (see snippet from above) as well as forwarding all request headers to heimdall and to let it forward headers, set by heimdall in its responses (here the Authorization header) to the upstream services.\nhttp_filters: # other http filter - name: envoy.filters.http.ext_authz typed_config: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34; (1) transport_api_version: V3 (2) http_service: server_uri: (3) uri: heimdall:4455 cluster: ext-authz timeout: 0.25s authorization_request: allowed_headers: (4) patterns: - safe_regex: google_re2: {} regex: \u0026#34;.*\u0026#34; authorization_response: (5) allowed_upstream_headers: patterns: - exact: authorization # other http filter 1 The type of the filter, we’re going to configure 2 Heimdall supports only the version 3 of the GRPC protocol defined by Envoy for that filter. So we set the required version here. 3 The reference to our previously configured cluster 4 Here, we say envoy to forward all headers from the received request to heimdall 5 And here, we instruct envoy to forward the Authorization header set bei heimdall in its response to envoy to the upstream service Envoy does not set X-Forwarded-* headers, as long as the envoy.filters.http.dynamic_forward_proxy is not configured. In such cases matching of URLs happens based on those URLs, used by Envoy while communicating with heimdall. That means your rules should ignore the scheme and host parts, respectively use the values specific for heimdall and not of the domain. Please follow Security Considerations if your rules rely on any of the X-Forwarded-* headers, and you integrate heimdall with envoy using http_service.\nIf you integrate heimdall with envoy via grpc_service (see below), spoofing of the aforesaid headers is not possible.\nUsing GRPC protocol The following snipped shows, how an External Authorization can be defined using grpc_service to let Envoy communicating with heimdall by making use of the previously defined cluster (see snippet from above). In that configuration envoy by default forwards all request header to heimdall and also forwards headers, set by heimdall in its responses to the upstream services.\nhttp_filters: # other http filter - name: envoy.filters.http.ext_authz typed_config: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34; (1) transport_api_version: V3 (2) grpc_service: (3) envoy_grpc: cluster_name: ext-authz # other http filter 1 The type of the filter, we’re going to configure. Same filter is used for both approaches, communication via HTTP and GRPC 2 Heimdall supports only the version 3 of the GRPC protocol defined by Envoy for that filter. So we set the required version here 3 The reference to our previously configured cluster Route-based Configuration Route base configuration happens exactly the same way as globally. There is also an option to fine tune or disable the external authorization service if required by making use of the ExtAuthzPerRoute filter. You can find an example in the official Envoy documentation.\nDemo Setup The Envoy configuration file shown below can be used to create a fully working setup based on the quickstart described in Protect an Application and set up to implement Edge-level Authorization Architecture. Just update the docker-compose.yaml file used in that guide and replace the entry for proxy service, with the one shown below. You can also remove all labels configurations, as these will have no effect.\n# docker-compose.yaml services: proxy: image: envoyproxy/envoy:v1.24.1 volumes: - ./envoy.yaml:/envoy.yaml:ro ports: - 9090:9090 command: -c /envoy.yaml # other services from the guide # envoy.yaml static_resources: listeners: - name: listener_0 address: socket_address: address: 0.0.0.0 port_value: 9090 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\u0026#34; stat_prefix: edge http_filters: - name: envoy.filters.http.ext_authz typed_config: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34; transport_api_version: V3 http_service: server_uri: uri: heimdall:4455 cluster: ext-authz timeout: 0.25s authorization_request: allowed_headers: patterns: - safe_regex: google_re2: {} regex: \u0026#34;.*\u0026#34; authorization_response: allowed_upstream_headers: patterns: - exact: authorization - name: envoy.filters.http.router typed_config: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.filters.http.router.v3.Router\u0026#34; route_config: virtual_hosts: - name: direct_response_service domains: [\u0026#34;*\u0026#34;] routes: - match: prefix: \u0026#34;/\u0026#34; route: cluster: services clusters: - name: ext-authz type: strict_dns load_assignment: cluster_name: ext-authz endpoints: - lb_endpoints: - endpoint: address: socket_address: address: heimdall port_value: 4455 - name: services connect_timeout: 5s type: strict_dns dns_lookup_family: V4_ONLY load_assignment: cluster_name: services endpoints: - lb_endpoints: - endpoint: address: socket_address: address: upstream port_value: 80 After starting the docker compose environment, you can run the curl commands shown in the referenced guide. This time however against envoy by using port 9090. E.g. $ curl -v 127.0.0.1:9090/anonymous.\nAdditional Resources The demo setup shown above is also available on GitHub.\n","description":"This guide explains how to integrate heimdall with Envoy.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://www.envoyproxy.io/\"\u003eEnvoy\u003c/a\u003e is a high performance distributed proxy designed for single services and applications, as well as a communication bus and “universal data plane” designed for large microservice “service mesh” architectures.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with Envoy proxy requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_integration_options\"\u003eIntegration Options\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnvoy makes integration with external authorization services, like heimdall possible via an \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e filter in two ways\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eeither via HTTP\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eor via GRPC\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both cases, the filter calls an external gRPC or HTTP service to check whether an incoming HTTP request is authorized or not. If the request is deemed unauthorized, then the request will be denied normally with 403 (Forbidden) response.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nEven envoy allows the authorization service sending additional custom metadata to the upstream when GRPC is used, heimdall does not make use of this option.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo integrate heimdall with Envoy globally, you need to configure two things:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ea \u003ccode\u003ecluster\u003c/code\u003e entry referencing the actual heimdall address, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe aforesaid filter in the http filter chain\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet provides an example on how to create a \u003ccode\u003ecluster\u003c/code\u003e instance referencing heimdall. It assumes, you have just one heimdall instance deployed, which is also available via \u003ccode\u003eheimdall\u003c/code\u003e DNS name.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eclusters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other cluster entries\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003estrict_dns\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_extension_protocol_options\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eenvoy.extensions.upstreams.http.v3.HttpProtocolOptions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexplicit_http_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp2_protocol_options\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eload_assignment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ecluster_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003elb_endpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esocket_address\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport_value\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4455\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other cluster entries\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe name of our cluster\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we configure envoy to communicate with heimdall by making use of HTTP 2. This configuration is only required if you want to integrate heimdall via Envoy’s \u003ccode\u003egrpc_service\u003c/code\u003e (see below), as otherwise envoy will use HTTP 1 for GRPC communication, which is actually not allowed by GRPC (only HTTP 2 is supported).\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe endpoints in the cluster. In this example, only one endpoint is configured.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can now include an \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e HTTP filter in the definition of the HTTP connection manager and depending on the used configuration, either configure the \u003ccode\u003ehttp_service\u003c/code\u003e and let it contain the required header name(s), heimdall sets in the HTTP responses (depends on your \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration), or configure the \u003ccode\u003egrpc_service\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_using_http_protocol\"\u003eUsing HTTP protocol\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snipped shows, how an \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e can be defined using \u003ccode\u003ehttp_service\u003c/code\u003e to let Envoy communicating with heimdall by making use of the previously defined \u003ccode\u003ecluster\u003c/code\u003e (see snippet from above) as well as forwarding all request headers to heimdall and to let it forward headers, set by heimdall in its responses (here the \u003ccode\u003eAuthorization\u003c/code\u003e header) to the upstream services.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ehttp_filters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other http filter\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoy.filters.http.ext_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etransport_api_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eV3\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ehttp_service\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eserver_uri\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003euri\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall:4455\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e0.25s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_request\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003epatterns\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003esafe_regex\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egoogle_re2\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eregex\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e.*\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_response\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eallowed_upstream_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epatterns\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexact\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthorization\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other http filter\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe type of the filter, we’re going to configure\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHeimdall supports only the version 3 of the GRPC protocol defined by Envoy for that filter. So we set the required version here.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe reference to our previously configured cluster\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we say envoy to forward all headers from the received request to heimdall\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAnd here, we instruct envoy to forward the \u003ccode\u003eAuthorization\u003c/code\u003e header set bei heimdall in its response to envoy to the upstream service\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnvoy does not set \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers, as long as the \u003ccode\u003eenvoy.filters.http.dynamic_forward_proxy\u003c/code\u003e is not configured. In such cases matching of URLs happens based on those URLs, used by Envoy while communicating with heimdall. That means your rules should ignore the scheme and host parts, respectively use the values specific for heimdall and not of the domain. Please follow \u003ca href=\"/docs/operations/security/#_http_headers_security_considerations\"\u003eSecurity Considerations\u003c/a\u003e if your rules rely on any of the \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers, and you integrate heimdall with envoy using \u003ccode\u003ehttp_service\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you integrate heimdall with envoy via \u003ccode\u003egrpc_service\u003c/code\u003e (see below), spoofing of the aforesaid headers is not possible.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_using_grpc_protocol\"\u003eUsing GRPC protocol\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snipped shows, how an \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e can be defined using \u003ccode\u003egrpc_service\u003c/code\u003e to let Envoy communicating with heimdall by making use of the previously defined \u003ccode\u003ecluster\u003c/code\u003e (see snippet from above). In that configuration envoy by default forwards all request header to heimdall and also forwards headers, set by heimdall in its responses to the upstream services.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ehttp_filters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other http filter\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoy.filters.http.ext_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etransport_api_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eV3\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003egrpc_service\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eenvoy_grpc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other http filter\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe type of the filter, we’re going to configure. Same filter is used for both approaches, communication via HTTP and GRPC\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHeimdall supports only the version 3 of the GRPC protocol defined by Envoy for that filter. So we set the required version here\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe reference to our previously configured cluster\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_route_based_configuration\"\u003eRoute-based Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRoute base configuration happens exactly the same way as globally. There is also an option to fine tune or disable the external authorization service if required by making use of the \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto#envoy-v3-api-msg-extensions-filters-http-ext-authz-v3-extauthzperroute\"\u003eExtAuthzPerRoute\u003c/a\u003e filter. You can find an example in the official \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/ext_authz_filter.html#per-route-configuration\"\u003eEnvoy documentation\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_demo_setup\"\u003eDemo Setup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe Envoy configuration file shown below can be used to create a fully working setup based on the quickstart described in \u003ca href=\"/docs/getting_started/protect_an_app/\"\u003eProtect an Application\u003c/a\u003e and set up to implement Edge-level Authorization Architecture. Just update the \u003ccode\u003edocker-compose.yaml\u003c/code\u003e file used in that guide and replace the entry for \u003ccode\u003eproxy\u003c/code\u003e service, with the one shown below. You can also remove all \u003ccode\u003elabels\u003c/code\u003e configurations, as these will have no effect.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# docker-compose.yaml\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eproxy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoyproxy/envoy:v1.24.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./envoy.yaml:/envoy.yaml:ro\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e9090:9090\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e-c /envoy.yaml\u003c/span\u003e\n\n \u003cspan class=\"c1\"\u003e# other services from the guide\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# envoy.yaml\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003estatic_resources\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elisteners\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003elistener_0\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esocket_address\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e0.0.0.0\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport_value\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e9090\u003c/span\u003e\n \u003cspan class=\"na\"\u003efilter_chains\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efilters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoy.filters.network.http_connection_manager\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003estat_prefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eedge\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_filters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoy.filters.http.ext_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003etransport_api_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eV3\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_service\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eserver_uri\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euri\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall:4455\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e0.25s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_request\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epatterns\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003esafe_regex\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egoogle_re2\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eregex\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e.*\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_response\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_upstream_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epatterns\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexact\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthorization\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoy.filters.http.router\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.filters.http.router.v3.Router\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroute_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evirtual_hosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edirect_response_service\u003c/span\u003e\n \u003cspan class=\"na\"\u003edomains\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e*\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e/\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservices\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eclusters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003estrict_dns\u003c/span\u003e\n \u003cspan class=\"na\"\u003eload_assignment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003elb_endpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esocket_address\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport_value\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4455\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservices\u003c/span\u003e\n \u003cspan class=\"na\"\u003econnect_timeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003estrict_dns\u003c/span\u003e\n \u003cspan class=\"na\"\u003edns_lookup_family\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eV4_ONLY\u003c/span\u003e\n \u003cspan class=\"na\"\u003eload_assignment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservices\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003elb_endpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esocket_address\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport_value\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e80\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAfter starting the docker compose environment, you can run the curl commands shown in the referenced guide. This time however against envoy by using port 9090. E.g. \u003ccode\u003e$ curl -v 127.0.0.1:9090/anonymous\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe demo setup shown above is also available on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Envoy Integration","url":"/guides/proxies/envoy/"},{"categories":null,"content":" Rules Sets Regular, respectively upstream specific rules must somehow be organized, versioned and also loaded. So, there must be some structure allowing all of that. That structure is defined by the so-called rule sets.\nA rule set can be considered to be just a file containing a list of rules and some additional meta information, like format version, name of the rule set and alike. Rule sets do also allow ordering of rules, e.g. with most specific matching expressions first allowing simpler matching expressions.\nThe actual format of the rule set is provider specific.\nProvider Types While all providers are different in the sense that they support different sources to load rule sets from, respectively monitor them, most of the providers use the same rule set format.\nThe following table gives an overview about existing providers\nProvider Rule Set Format Short Description File-System\nYAML or JSON\nLoads rule set files from the local file system\nHTTP Endpoint\nYAML or JSON\nLoads rule sets from an HTTP(s) endpoint\nCloud Blob\nYAML or JSON\nLoads rule sets from cloud blobs, like AWS S3, Google Cloud Storage, Azure Cloud Storage and alike.\nKubernetes\nCustom Resource\nLoads rule sets made available to a kubernetes cluster as customer resources.\n","description":"When rules define the behavior in sense of the desired authentication and authorization aspects, then the providers are those entities, which manage the lifecycle of these. That are the providers, which load, reload or remove rules when new rules appears, changes are detected, or rules are deleted.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_rules_sets\"\u003eRules Sets\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRegular, respectively upstream specific rules must somehow be organized, versioned and also loaded. So, there must be some structure allowing all of that. That structure is defined by the so-called rule sets.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA rule set can be considered to be just a file containing a list of rules and some additional meta information, like format version, name of the rule set and alike. Rule sets do also allow ordering of rules, e.g. with most specific matching expressions first allowing simpler matching expressions.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual format of the rule set is provider specific.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_provider_types\"\u003eProvider Types\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhile all providers are different in the sense that they support different sources to load rule sets from, respectively monitor them, most of the providers use the same rule set format.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following table gives an overview about existing providers\u003c/p\u003e\n\u003c/div\u003e\n\u003ctable class=\"tableblock frame-all grid-all stretch\"\u003e\n\u003ccolgroup\u003e\n\u003ccol style=\"width: 22.2222%;\"/\u003e\n\u003ccol style=\"width: 22.2222%;\"/\u003e\n\u003ccol style=\"width: 55.5556%;\"/\u003e\n\u003c/colgroup\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eProvider\u003c/strong\u003e\u003c/th\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eRule Set Format\u003c/strong\u003e\u003c/th\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eShort Description\u003c/strong\u003e\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ca href=\"/docs/rules/providers/#_filesystem\"\u003eFile-System\u003c/a\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eYAML or JSON\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eLoads rule set files from the local file system\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ca href=\"/docs/rules/providers/#_http_endpoint\"\u003eHTTP Endpoint\u003c/a\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eYAML or JSON\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eLoads rule sets from an HTTP(s) endpoint\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ca href=\"/docs/rules/providers/#_cloud_blob\"\u003eCloud Blob\u003c/a\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eYAML or JSON\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eLoads rule sets from cloud blobs, like AWS S3, Google Cloud Storage, Azure Cloud Storage and alike.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ca href=\"/docs/rules/providers/#_kubernetes\"\u003eKubernetes\u003c/a\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eCustom Resource\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eLoads rule sets made available to a kubernetes cluster as customer resources.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Concepts"],"tags":null,"title":"Rule Provider","url":"/docs/concepts/provider/"},{"categories":null,"content":" Envoy Gateway is an open source project for managing Envoy Proxy as a Kubernetes-based application gateway by making use of the Gateway API resources.\nPrerequisites A kubernetes cluster\nDeployed Envoy Gateway (See here for installation options)\nDeployed GatewayClass resource that matches Envoy Gateway’s configured controllerName (typically gateway.envoyproxy.io/gatewayclass-controller), as well as a deployed Gateway resource.\nheimdall installed and operated in Decision Operation Mode.\nIntegration Options Technically, the integration happens the same way as with Envoy itself by making use of the External Authorization filter, and can be done in two ways:\neither via HTTP\nor via gRPC (recommended)\nIn both cases, the filter calls an external gRPC or HTTP service (here heimdall) to check whether an incoming HTTP request is authorized or not. If heimdall responses with 2xx the request is forwarded to the upstream service, otherwise the response from heimdall is returned to the caller.\nIn case of Envoy Gateway the abovesaid configuration happens via a SecurityPolicy custom resource, that can be linked to a Gateway, HTTPRoute, or a GRPCRoute resource.\nAs of today, there is a limitation in the implementation of the Envoy Gateway - it does not allow cross-namespace reference of external auth services (see also envoyproxy/gateway#3322). That means, the HTTPRoute, the Gateway resource and heimdall must be deployed in the same namespace. Global Configuration To integrate heimdall with the gateway globally, that is, each and every request will be forwarded to heimdall for authentication and authorization purposes first, create a SecurityPolicy as shown below in the namespace, the Gateway resource is deployed into.\napiVersion: gateway.envoyproxy.io/v1alpha1 kind: SecurityPolicy metadata: name: ext-auth-heimdall (1) namespace: heimdall (2) spec: targetRef: (3) group: gateway.networking.k8s.io kind: Gateway name: eg namespace: heimdall extAuth: grpc: backendRef: (4) name: heimdall port: 4455 namespace: heimdall 1 The name of the SecurityPolicy. You can change it to any other value if you like. 2 The namespace for the policy. It must be the same namespace the Gateway resource and heimdall are deployed into. So change it to your namespace. 3 Defines the Gateway resource, this policy should be applied to. Change the name property to the name of your Gateway resource and the namespace property to the proper namespace (same as in 2) 4 Defines the reference to the heimdall Service using the gRPC protocol. Change the name and the namespace to the proper values of your setup. Route-level Configuration The integration on the route level happens similar to the global integration. The difference is that the SecurityPolicy is applied to an HTTPRoute as shown below and not the Gateway resource.\napiVersion: gateway.envoyproxy.io/v1alpha1 kind: SecurityPolicy metadata: name: ext-auth-example (1) namespace: heimdall (2) spec: targetRef: (3) group: gateway.networking.k8s.io kind: HTTPRoute name: heimdall extAuth: grpc: backendRef: (4) name: heimdall port: 4455 namespace: heimdall 1 The name of the SecurityPolicy. You can change it to any other value if you like. 2 The namespace for the policy. It must be the same namespace the HTTPRoute resource is deployed into, so the namespace, your application is deployed to. So change it to your namespace. 3 Defines the HTTPRoute resource, this policy should be applied to. Change the name property to the name of your HTTPRoute resource and the namespace property to the proper namespace (same as in 2) 4 Defines the reference to the heimdall Service using the gRPC protocol. Change the name and the namespace to the proper values of your setup. Security Considerations The configuration options shown above are highly insecure, as the communication from the gateway to heimdall happens over plain HTTP. Therefore, it is highly recommended to enable TLS. This can be achieved by enabling TLS for heimdall and attaching a BackendTLSPolicy resource shown below to heimdall’s Service.\napiVersion: gateway.networking.k8s.io/v1alpha2 kind: BackendTLSPolicy metadata: name: heimdall-btls namespace: heimdall (1) spec: targetRef: (2) group: \u0026#39;\u0026#39; kind: Service namespace: heimdall name: heimdall sectionName: \u0026#34;4455\u0026#34; tls: (3) caCertRefs: - name: demo-ca (4) group: \u0026#39;\u0026#39; kind: ConfigMap hostname: heimdall (5) 1 Change it to the namespace in which heimdall is deployed 2 The reference to heimdall’s Service. Change the name and the namespace to the proper values. 3 Here we configure the reference to the ConfigMap with the certificate of the CA, used to issue a TLS server authentication certificate for heimdall, as well as the hostname used by heimdall (and present in the SAN extension of heimdall’s TLS certificate). The ConfigMap must be in the same namespace as the BackendTLSPolicy. 4 The name of the ConfigMap. Change it to the proper value. 5 The expected hostname used by heimdall. Change it to the proper value. Additional Resources A fully working example with Envoy Gateway is also available on GitHub.\nYou can find the official external authentication guide for Envoy Gateway here. It contains a fully working setup with a demo application.\nSecure Gateways is a highly recommended read as well.\n","description":"This guide explains how to integrate heimdall with Envoy Gateway.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://gateway.envoyproxy.io\"\u003eEnvoy Gateway\u003c/a\u003e is an open source project for managing \u003ca href=\"https://www.envoyproxy.io/\"\u003eEnvoy Proxy\u003c/a\u003e as a Kubernetes-based application gateway by making use of the \u003ca href=\"https://gateway-api.sigs.k8s.io/\"\u003eGateway API\u003c/a\u003e resources.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eA kubernetes cluster\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDeployed Envoy Gateway (See \u003ca href=\"https://gateway.envoyproxy.io/v1.0.1/install/\"\u003ehere\u003c/a\u003e for installation options)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDeployed \u003ca href=\"https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.GatewayClass\"\u003e\u003ccode\u003eGatewayClass\u003c/code\u003e\u003c/a\u003e resource that matches Envoy Gateway’s configured \u003ccode\u003econtrollerName\u003c/code\u003e (typically \u003ccode\u003egateway.envoyproxy.io/gatewayclass-controller\u003c/code\u003e), as well as a deployed \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e resource.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eheimdall installed and operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_integration_options\"\u003eIntegration Options\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTechnically, the integration happens the same way as with \u003ca href=\"/guides/proxies/envoy/\"\u003eEnvoy\u003c/a\u003e itself by making use of the \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e filter, and can be done in two ways:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eeither via HTTP\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eor via gRPC (recommended)\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both cases, the filter calls an external gRPC or HTTP service (here heimdall) to check whether an incoming HTTP request is authorized or not. If heimdall responses with \u003ccode\u003e2xx\u003c/code\u003e the request is forwarded to the upstream service, otherwise the response from heimdall is returned to the caller.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn case of Envoy Gateway the abovesaid configuration happens via a \u003ca href=\"https://gateway.envoyproxy.io/contributions/design/security-policy/\"\u003e\u003ccode\u003eSecurityPolicy\u003c/code\u003e\u003c/a\u003e custom resource, that can be linked to a \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/httproute\"\u003e\u003ccode\u003eHTTPRoute\u003c/code\u003e\u003c/a\u003e, or a \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/grpcroute\"\u003e\u003ccode\u003eGRPCRoute\u003c/code\u003e\u003c/a\u003e resource.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAs of today, there is a limitation in the implementation of the Envoy Gateway - it does not allow cross-namespace reference of external auth services (see also \u003ca href=\"https://github.com/envoyproxy/gateway/issues/3322\"\u003eenvoyproxy/gateway#3322\u003c/a\u003e). That means, the \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/httproute\"\u003e\u003ccode\u003eHTTPRoute\u003c/code\u003e\u003c/a\u003e, the \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e resource and heimdall must be deployed in the same namespace.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo integrate heimdall with the gateway globally, that is, each and every request will be forwarded to heimdall for authentication and authorization purposes first, create a \u003ca href=\"https://gateway.envoyproxy.io/contributions/design/security-policy/\"\u003e\u003ccode\u003eSecurityPolicy\u003c/code\u003e\u003c/a\u003e as shown below in the namespace, the \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e resource is deployed into.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egateway.envoyproxy.io/v1alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSecurityPolicy\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-auth-heimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etargetRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003egroup\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egateway.networking.k8s.io\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGateway\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eeg\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eextAuth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egrpc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebackendRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4455\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe name of the \u003ccode\u003eSecurityPolicy\u003c/code\u003e. You can change it to any other value if you like.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe namespace for the policy. It must be the same namespace the \u003ccode\u003eGateway\u003c/code\u003e resource and heimdall are deployed into. So change it to your namespace.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eDefines the \u003ccode\u003eGateway\u003c/code\u003e resource, this policy should be applied to. Change the \u003ccode\u003ename\u003c/code\u003e property to the name of your \u003ccode\u003eGateway\u003c/code\u003e resource and the \u003ccode\u003enamespace\u003c/code\u003e property to the proper namespace (same as in 2)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eDefines the reference to the heimdall \u003ccode\u003eService\u003c/code\u003e using the gRPC protocol. Change the \u003ccode\u003ename\u003c/code\u003e and the \u003ccode\u003enamespace\u003c/code\u003e to the proper values of your setup.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_route_level_configuration\"\u003eRoute-level Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe integration on the route level happens similar to the \u003ca href=\"#_global_configuration\"\u003eglobal integration\u003c/a\u003e. The difference is that the \u003ca href=\"https://gateway.envoyproxy.io/contributions/design/security-policy/\"\u003e\u003ccode\u003eSecurityPolicy\u003c/code\u003e\u003c/a\u003e is applied to an \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/httproute\"\u003e\u003ccode\u003eHTTPRoute\u003c/code\u003e\u003c/a\u003e as shown below and not the \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e resource.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egateway.envoyproxy.io/v1alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSecurityPolicy\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-auth-example\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etargetRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003egroup\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egateway.networking.k8s.io\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eHTTPRoute\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eextAuth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egrpc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebackendRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4455\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe name of the \u003ccode\u003eSecurityPolicy\u003c/code\u003e. You can change it to any other value if you like.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe namespace for the policy. It must be the same namespace the \u003ccode\u003eHTTPRoute\u003c/code\u003e resource is deployed into, so the namespace, your application is deployed to. So change it to your namespace.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eDefines the \u003ccode\u003eHTTPRoute\u003c/code\u003e resource, this policy should be applied to. Change the \u003ccode\u003ename\u003c/code\u003e property to the name of your \u003ccode\u003eHTTPRoute\u003c/code\u003e resource and the \u003ccode\u003enamespace\u003c/code\u003e property to the proper namespace (same as in 2)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eDefines the reference to the heimdall \u003ccode\u003eService\u003c/code\u003e using the gRPC protocol. Change the \u003ccode\u003ename\u003c/code\u003e and the \u003ccode\u003enamespace\u003c/code\u003e to the proper values of your setup.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_security_considerations\"\u003eSecurity Considerations\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration options shown above are highly insecure, as the communication from the gateway to heimdall happens over plain HTTP. Therefore, it is highly recommended to enable TLS. This can be achieved by enabling TLS for heimdall and attaching a \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy/\"\u003e\u003ccode\u003eBackendTLSPolicy\u003c/code\u003e\u003c/a\u003e resource shown below to heimdall’s \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/service/\"\u003e\u003ccode\u003eService\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egateway.networking.k8s.io/v1alpha2\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBackendTLSPolicy\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-btls\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etargetRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003egroup\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eService\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003esectionName\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e4455\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ecaCertRefs\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo-ca\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003egroup\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eConfigMap\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehostname\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eChange it to the namespace in which heimdall is deployed\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe reference to heimdall’s \u003ccode\u003eService\u003c/code\u003e. Change the \u003ccode\u003ename\u003c/code\u003e and the \u003ccode\u003enamespace\u003c/code\u003e to the proper values.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we configure the reference to the \u003ccode\u003eConfigMap\u003c/code\u003e with the certificate of the CA, used to issue a TLS server authentication certificate for heimdall, as well as the hostname used by heimdall (and present in the SAN extension of heimdall’s TLS certificate). The \u003ccode\u003eConfigMap\u003c/code\u003e must be in the same namespace as the \u003ccode\u003eBackendTLSPolicy\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe name of the \u003ccode\u003eConfigMap\u003c/code\u003e. Change it to the proper value.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe expected hostname used by heimdall. Change it to the proper value.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eA fully working example with Envoy Gateway is also available on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eYou can find the official external authentication guide for Envoy Gateway \u003ca href=\"https://gateway.envoyproxy.io/v1.0.1/tasks/security/ext-auth/\"\u003ehere\u003c/a\u003e. It contains a fully working setup with a demo application.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://gateway.envoyproxy.io/v1.0.1/tasks/security/secure-gateways/\"\u003eSecure Gateways\u003c/a\u003e is a highly recommended read as well.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Envoy Gateway Integration","url":"/guides/proxies/envoy_gateway/"},{"categories":null,"content":" Decision Mode In this mode you can integrate heimdall with existing reverse proxies, or API gateways (like Kong, NGNIX, Envoy, Traefik and much more)\nFigure 1. Decision Deployment In this mode heimdall can be integrated with most probably all modern API gateways and reverse proxies as a so-called \u0026#34;authentication middleware\u0026#34;. Here the reverse proxy, respectively API gateway integrating with heimdall, will forward requests to heimdall by making use of its main service endpoint for authentication and authorization purposes. As in the Reverse Proxy mode, heimdall will check if these requests match and satisfy the conditions defined in the available rules. If not, heimdall returns an error to its client (here API gateway/reverse proxy). If the rule execution was successful, it also responds to the API gateway/reverse proxy with 200 OK (can be overridden if required) and sets headers/cookies, specified in the matched rule, which are then forwarded to the upstream service.\nStarting heimdall in this mode happens via the serve decision command. Head over to the description of CLI as well as to corresponding configuration options for more details.\nExample 1. Decision Service Example Imagine following request hits heimdall (sent to it by an API gateway)\nGET /my-service/api HTTP/1.1 Host: heimdall:4455 X-Forwarded-Host: my-backend-service Some payload And there is a rule, which allows anonymous requests and sets a header with subject id set to anonymous like this\nid: rule:my-service:anonymous-api-access match: routes: - path: /my-service/api scheme: http hosts: - type: exact value: my-backend-service methods: - GET execute: - authenticator: anonymous-authn - finalizer: id-header Then heimdall will respond with:\nHTTP/1.1 200 OK X-User-ID: anonymous Proxy Mode In this operation mode you can use heimdall as a reverse proxy in front of your upstream API or web server.\nFigure 2. Proxy Deployment In this mode heimdall forwards requests to the upstream service if these satisfy the conditions defined in matched rules. Otherwise, heimdall returns an error to the client. If the execution of the rule was successful, it also forwards additional headers, specified in the rule to the upstream service.\nStarting heimdall in this mode happens via the serve proxy command. Head over to the description of CLI as well as to main service configuration options for more details.\nExample 2. Reverse Proxy Example Imagine following request hits heimdall\nGET /my-service/api HTTP/1.1 Host: heimdall:4455 Some payload And there is a rule, which allows anonymous requests and sets a header with subject id set to anonymous like this\nid: rule:my-service:anonymous-api-access match: routes: - path: /my-service/api methods: - GET forward_to: host: my-backend-service:8888 execute: - authenticator: anonymous-authn - finalizer: id-header Then the request will be forwarded as follows:\nGET /my-service/api HTTP/1.1 Host: my-backend-service:8888 X-User-ID: anonymous Some payload ","description":"To support different deployment scenarios, heimdall supports two operating modes.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_decision_mode\"\u003eDecision Mode\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this mode you can integrate heimdall with existing reverse proxies, or API gateways (like \u003ca href=\"https://konghq.com/\"\u003eKong\u003c/a\u003e, \u003ca href=\"https://nginx.org\"\u003eNGNIX\u003c/a\u003e, \u003ca href=\"https://www.envoyproxy.io/\"\u003eEnvoy\u003c/a\u003e, \u003ca href=\"https://traefik.io/\"\u003eTraefik\u003c/a\u003e and much more)\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_fig_heimdall_decision_deployment\" class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-6aa79a33899aaf938fd0bdc4e82460e2.svg\" alt=\"Diagram\" width=\"1020\" height=\"490\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 1. Decision Deployment\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this mode heimdall can be integrated with most probably all modern API gateways and reverse proxies as a so-called \u0026#34;authentication middleware\u0026#34;. Here the reverse proxy, respectively API gateway integrating with heimdall, will forward requests to heimdall by making use of its main service endpoint for authentication and authorization purposes. As in the \u003ca href=\"#_proxy_mode\"\u003eReverse Proxy\u003c/a\u003e mode, heimdall will check if these requests match and satisfy the conditions defined in the available rules. If not, heimdall returns an error to its client (here API gateway/reverse proxy). If the rule execution was successful, it also responds to the API gateway/reverse proxy with \u003ccode\u003e200 OK\u003c/code\u003e (can be overridden if required) and sets headers/cookies, specified in the matched rule, which are then forwarded to the upstream service.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eStarting heimdall in this mode happens via the \u003ccode\u003eserve decision\u003c/code\u003e command. Head over to the description of \u003ca href=\"/docs/operations/cli/\"\u003eCLI\u003c/a\u003e as well as to \u003ca href=\"/docs/services/main/\"\u003ecorresponding configuration options\u003c/a\u003e for more details.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Decision Service Example\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine following request hits heimdall (sent to it by an API gateway)\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eGET /my-service/api HTTP/1.1\nHost: heimdall:4455\nX-Forwarded-Host: my-backend-service\n\nSome payload\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAnd there is a rule, which allows anonymous requests and sets a header with subject id set to \u003ccode\u003eanonymous\u003c/code\u003e like this\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:my-service:anonymous-api-access\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/my-service/api\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-backend-service\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous-authn\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eid-header\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThen heimdall will respond with:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eHTTP/1.1 200 OK\nX-User-ID: anonymous\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_proxy_mode\"\u003eProxy Mode\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this operation mode you can use heimdall as a reverse proxy in front of your upstream API or web server.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_fig_heimdall_proxy_deployment\" class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-bd38a9b34b3de344495c4271ed4b394a.svg\" alt=\"Diagram\" width=\"980\" height=\"308\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 2. Proxy Deployment\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this mode heimdall forwards requests to the upstream service if these satisfy the conditions defined in matched rules. Otherwise, heimdall returns an error to the client. If the execution of the rule was successful, it also forwards additional headers, specified in the rule to the upstream service.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eStarting heimdall in this mode happens via the \u003ccode\u003eserve proxy\u003c/code\u003e command. Head over to the description of \u003ca href=\"/docs/operations/cli/\"\u003eCLI\u003c/a\u003e as well as to \u003ca href=\"/docs/services/main/\"\u003emain service configuration options\u003c/a\u003e for more details.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Reverse Proxy Example\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine following request hits heimdall\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eGET /my-service/api HTTP/1.1\nHost: heimdall:4455\n\nSome payload\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAnd there is a rule, which allows anonymous requests and sets a header with subject id set to \u003ccode\u003eanonymous\u003c/code\u003e like this\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:my-service:anonymous-api-access\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/my-service/api\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n\u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-backend-service:8888\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous-authn\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eid-header\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThen the request will be forwarded as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eGET /my-service/api HTTP/1.1\nHost: my-backend-service:8888\nX-User-ID: anonymous\n\nSome payload\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Concepts"],"tags":null,"title":"Operating Modes","url":"/docs/concepts/operating_modes/"},{"categories":null,"content":" HAProxy (High Availability Proxy) is a popular open source, fast, and reliable solution providing load balancer and reverse proxy features for TCP- and HTTP-based applications, capable handling heavy load traffic and rerouting requests seamlessly across multiple workloads (e.g. web, application, database).\nVanilla HAProxy HAProxy is highly extensible thanks to Lua scripting support. For that reason the vanilla HAProxy does not implement any means of external authorization support and requires custom Lua code to achieve integration with heimdall.\nHAProxy Ingress Controller The HAProxy Ingress Controller has the required integration options however in place. That way, delegation of authentication and authorization to heimdall operated in Decision Mode is easily possible using the Ingress rule annotations as well as globally, with latter allowing implementation of secure defaults for all your workloads\nIn both cases, if heimdall answers with a 2XX code, HAProxy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\nThis integration requires proper configuration of trusted_proxies. Global integration There seems to be a bug in the implementation of the HAProxy Ingress controller. Even the below description is based on the official documentation, it does not work. Corresponding ticket has been filed: https://github.com/jcmoraisjr/haproxy-ingress/issues/1105. Please check the status of this ticket first. To have the integration configured globally and used for all workloads, you have to add the keys shown in the snipped below to the data of the ConfigMap used by the haproxy ingress controller.\napiVersion: v1 kind: ConfigMap data: auth-url: \u0026#34;https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34; (1) auth-headers-succeed: \u0026#34;authorization\u0026#34; (2) headers: | (3) X-Forwarded-Uri: %[pathq] X-Forwarded-Method: %[method] X-Forwarded-Host: %[req.hdr(host)] 1 Configures the controller to use heimdall’s main service endpoint with \u0026lt;heimdall service name\u0026gt;, \u0026lt;namespace\u0026gt; and \u0026lt;port\u0026gt; depending on your configuration. 2 Let HAProxy forward the Authorization header set by heimdall to the upstream service upon successful response. This configuration depends on your Contextualizers and Finalizers configuration. There is currently a limitation in HAProxy Ingress Controller regarding the case-insensitivity for headers. Since heimdall returns the header in lower-case, it is important to set the names of the required to be forwarded headers in lower case as well. 3 Configures the required headers to pass the information about the used HTTP scheme, host and port, request path and used query parameters to be forwarded to heimdall. X-Forwarded-Proto is not used, as it is already set by HAProxy by default. If the installation of haproxy ingress controller happens using helm, these keys can easily be added by making use of the controller.config property (see also Helm chart configuration options for details).\nIngress Rule based integration The code snipped below shows the required annotations on the ingress rule. It uses the same configuration keys as the global configuration prefixed with haproxy-ingress.github.io/\nannotations: haproxy-ingress.github.io/auth-url: \u0026#34;https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34; haproxy-ingress.github.io/auth-headers-succeed: \u0026#34;authorization\u0026#34; haproxy-ingress.github.io/headers: | X-Forwarded-Uri: %[pathq] X-Forwarded-Method: %[method] X-Forwarded-Host: %[req.hdr(host)] Additional Resources Checkout the examples on GitHub for a working demo.\n","description":"Explains how to integrate heimdall with HAProxy.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://www.haproxy.com/\"\u003eHAProxy\u003c/a\u003e (High Availability Proxy) is a popular open source, fast, and reliable solution providing load balancer and reverse proxy features for TCP- and HTTP-based applications, capable handling heavy load traffic and rerouting requests seamlessly across multiple workloads (e.g. web, application, database).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_vanilla_haproxy\"\u003eVanilla HAProxy\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHAProxy is highly extensible thanks to Lua scripting support. For that reason the vanilla HAProxy does not implement any means of external authorization support and requires custom Lua code to achieve integration with heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_haproxy_ingress_controller\"\u003eHAProxy Ingress Controller\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"https://haproxy-ingress.github.io/\"\u003eHAProxy Ingress Controller\u003c/a\u003e has the required \u003ca href=\"https://haproxy-ingress.github.io/docs/configuration/keys/#auth-external\"\u003eintegration options\u003c/a\u003e however in place. That way, delegation of authentication and authorization to heimdall operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Mode\u003c/a\u003e is easily possible using the Ingress rule annotations as well as globally, with latter allowing implementation of secure defaults for all your workloads\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both cases, if heimdall answers with a 2XX code, HAProxy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis integration requires proper configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_global_integration\"\u003eGlobal integration\u003c/h3\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThere seems to be a bug in the implementation of the HAProxy Ingress controller. Even the below description is based on the official documentation, it does not work. Corresponding ticket has been filed: \u003ca href=\"https://github.com/jcmoraisjr/haproxy-ingress/issues/1105\" class=\"bare\"\u003ehttps://github.com/jcmoraisjr/haproxy-ingress/issues/1105\u003c/a\u003e. Please check the status of this ticket first.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo have the integration configured globally and used for all workloads, you have to add the keys shown in the snipped below to the \u003ccode\u003edata\u003c/code\u003e of the \u003ca href=\"https://haproxy-ingress.github.io/docs/configuration/keys/#configmap\"\u003eConfigMap\u003c/a\u003e used by the haproxy ingress controller.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ev1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eConfigMap\u003c/span\u003e\n\u003cspan class=\"na\"\u003edata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth-url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://\u0026lt;heimdall\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eservice\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eauth-headers-succeed\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eauthorization\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Uri: %[pathq]\u003c/span\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Method: %[method]\u003c/span\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Host: %[req.hdr(host)]\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures the controller to use heimdall’s main service endpoint with \u003ccode\u003e\u0026lt;heimdall service name\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;namespace\u0026gt;\u003c/code\u003e and \u003ccode\u003e\u0026lt;port\u0026gt;\u003c/code\u003e depending on your configuration.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet HAProxy forward the \u003ccode\u003eAuthorization\u003c/code\u003e header set by heimdall to the upstream service upon successful response. This configuration depends on\nyour \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThere is currently a limitation in HAProxy Ingress Controller regarding the case-insensitivity for headers. Since heimdall returns the header in lower-case, it is important to set the names of the required to be forwarded headers in lower case as well.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures the required headers to pass the information about the used HTTP scheme, host and port, request path and used query parameters to be forwarded to heimdall. \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e is not used, as it is already set by HAProxy by default.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the installation of haproxy ingress controller happens using helm, these keys can easily be added by making use of the \u003ccode\u003econtroller.config\u003c/code\u003e property (see also \u003ca href=\"https://github.com/haproxy-ingress/charts/blob/release-0.14/haproxy-ingress/README.md#configuration\"\u003eHelm chart configuration options\u003c/a\u003e for details).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_ingress_rule_based_integration\"\u003eIngress Rule based integration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe code snipped below shows the required annotations on the ingress rule. It uses the same configuration keys as the global configuration prefixed with \u003ccode\u003ehaproxy-ingress.github.io/\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eannotations\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehaproxy-ingress.github.io/auth-url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://\u0026lt;heimdall\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eservice\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehaproxy-ingress.github.io/auth-headers-succeed\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eauthorization\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehaproxy-ingress.github.io/headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Uri: %[pathq]\u003c/span\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Method: %[method]\u003c/span\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Host: %[req.hdr(host)]\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCheckout the examples on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e for a working demo.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"HAProxy Integration","url":"/guides/proxies/haproxy/"},{"categories":null,"content":" Istio is an open-source service mesh that extends Kubernetes’ capabilities, providing a uniform way to observe, secure, and connect microservices. It also functions as a Kubernetes-based application gateway, using either its built-in Ingress Gateway, the Kubernetes Ingress, or the Gateway API resources for configuration.\nPrerequisites A kubernetes cluster\nDeployed Istio (See here for installation options)\nheimdall installed and operated in Decision Operation Mode.\nTo allow heimdall communicating with services running in the mesh, add the certificate of the CA used by Istio to heimdall’s trust store. Integration Options Technically, the integration works similarly to the Envoy setup by utilizing the External Authorization filter. This can be implemented in two ways:\nvia HTTP\nvia gRPC (recommended)\nIn both approaches, the filter sends a request to an external gRPC or HTTP service (in this case, heimdall) to determine if the incoming HTTP request is authorized. If heimdall responds with a 2xx status code, the request is forwarded to the upstream service. Otherwise, heimdall’s response is returned to the caller.\nFor Istio, this integration involves configuring an envoyExtAuthzHttp or envoyExtAuthzGrpc ExtensionProvider for heimdall in the mesh configuration. The configured extension can then be enabled via an AuthorizationPolicy resource. Depending on its definition, heimdall can be used globally for all requests served through a particular gateway, or selectively for specific requests only.\nThe sections below explain how to achieve this for Istio’s Ingress Gateway, as well as using the Kubernetes Gateway API.\nThis guide assumes that Istio and heimdall are installed in the same cluster. If they are not, you will need to register heimdall in Istio’s internal service registry using a ServiceEntry resource. Common Configuration Register the Extension Provider As mentioned earlier, registering an extension provider in Istio’s mesh configuration is required. Follow these steps:\nEdit the mesh configuration: Run kubectl edit configmap istio -n istio-system to open the mesh configuration for editing.\nAdd the extensionProvider configuration: Insert the following settings into the mesh configuration:\napiVersion: v1 data: mesh: |- # Add the following contents: extensionProviders: - name: heimdall-ext-auth (1) envoyExtAuthzGrpc: (2) service: heimdall.heimdall.svc.cluster.local (3) port: \u0026#34;4455\u0026#34; 1 heimdall-ext-auth is the name of our extension provider, which will be referenced later in the AuthorizationPolicy configuration. 2 We’re using a gRPC based implementation here. However, since Istio does not automatically configure Envoy to use HTTP/2 for gRPC calls, it requires an additional EnvoyFilter resource. This appears to be a bug in Istio’s implementation. 3 Heimdall’s address within the cluster, which the extension provider will use for communication. Alternatively, you can make use of envoyExtAuthzHttp extension provider. In that case insert the following settings:\napiVersion: v1 data: mesh: |- # Add the following contents: extensionProviders: - name: heimdall-ext-auth envoyExtAuthzHttp: service: heimdall.heimdall.svc.cluster.local port: \u0026#34;4455\u0026#34; includeRequestHeadersInCheck: [ \u0026#34;authorization\u0026#34;, \u0026#34;cookie\u0026#34;, \u0026#34;accept\u0026#34;, \u0026#34;x-forwarded-for\u0026#34;, \u0026#34;x-forwarded-proto\u0026#34;, \u0026#34;x-forwarded-host\u0026#34; ] (1) headersToUpstreamOnAllow: [ \u0026#34;authorization\u0026#34; ] (2) 1 Include further headers, you expect to make use of in your heimdall rules. 2 Include further headers, you expect to be set in your heimdall rules and which should be forwarded to the upstream service. Deploy the following EnvoyFilter resource to correct the cluster configuration that Istio sets up for the heimdall service.\nThis is only required if you made use of the envoyExtAuthzGrpc provider as shown above. apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: http2-protocol-for-heimdall namespace: istio-system (1) spec: configPatches: - applyTo: CLUSTER (2) match: (3) context: GATEWAY cluster: name: outbound|4455||heimdall.heimdall.svc.cluster.local patch: operation: MERGE value: typed_extension_protocol_options: (4) envoy.extensions.upstreams.http.v3.HttpProtocolOptions: \u0026#34;@type\u0026#34;: type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicit_http_config: http2_protocol_options: {} 1 The namespace where the Istio control plane is deployed (the config root namespace). That way this filter is used each time envoy instance is created by Istio. 2 Specifies that we want to apply the patch for a cluster 3 Since we want this patch to be applied for gateways only, we limit the context accordingly 4 This is the actual config we would like to merge into the cluster definition to enable HTTP/2 support. Configure additional CA certificates This step is optional and only necessary if heimdall is configured to use TLS for inbound traffic.\nIt is highly recommended to secure the communication between the Istio-managed gateway and heimdall. Instead of configuring heimdall to handle TLS directly, you can let Istio inject a proxy into heimdall’s pod to manage TLS termination. However, this approach introduces an additional network hop, which could negatively impact performance. Instruct Istio to trust heimdall’s certificate by applying the following DestinationRule resource in the Istio root configuration namespace:\napiVersion: networking.istio.io/v1 kind: DestinationRule metadata: name: heimdall namespace: istio-system spec: host: heimdall.heimdall.svc.cluster.local trafficPolicy: tls: mode: SIMPLE sni: heimdall.heimdall.svc.cluster.local (1) credentialName: cacerts (2) 1 If sni is not set, it defaults to the downstream HTTP Host or Authority header, which will cause an error on the heimdall side because the name will not match the DNS entries in heimdall’s certificate. 2 The secret contains the certificate of the CA that issued heimdall’s certificate. Without this, Envoy won’t trust heimdall’s certificate. This secret must be available in every namespace where Istio creates a gateway. Route the requests through heimdall With the previous configuration in place, we can now instruct Istio to route the ingress traffic through heimdall first.\nCreate the following AuthorizationPolicy in Istio’s root configuration namespace:\napiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: heimdall namespace: istio-system spec: selector: matchLabels: (1) istio: ingressgateway action: CUSTOM provider: name: heimdall-ext-auth (2) rules: - {} (3) 1 This policy is specifically intended for gateways, excluding injected sidecars. 2 Here, we reference the extension provider that was configured earlier. 3 The policy is set to apply universally, with no specific conditions, hence the empty rules. With this configuration completed, you can proceed to deploy the necessary gateway resources.\nIngress Gateway Configuration Simply create the Ingress Gateway resource and define the VirtualService resources for your services according to your requirements. No further configuration is necessary.\nKubenetes Gateway API As of this writing, Istio’s implementation of the Gateway API appears incomplete. It lacks the necessary Role and RoleBinding to access the Secret containing additional CA certificates. Without these, the Envoy instances cannot access the secret, preventing them from trusting heimdall’s certificate. To resolve this, apply the following resources in the namespace where the Gateway will be installed:\napiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: gateway.istio.io/managed: istio.io-gateway-controller gateway.networking.k8s.io/gateway-name: istio-gw istio: ingressgateway istio.io/gateway-name: istio-gw name: istio-gw-istio namespace: istio-gw rules: - apiGroups: - \u0026#34;\u0026#34; resources: - secrets verbs: - get - watch - list --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: gateway.istio.io/managed: istio.io-gateway-controller gateway.networking.k8s.io/gateway-name: istio-gw istio: ingressgateway istio.io/gateway-name: istio-gw name: istio-gw-istio namespace: istio-gw roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: istio-gw-istio subjects: - kind: ServiceAccount name: istio-gw-istio (1) 1 Change the name of the service account accordingly; it follows the pattern \u0026lt;namespace\u0026gt;-istio. Now, you can create the required Gateway and HTTPRoute resources for your service. When creating the Gateway resource, ensure you add the istio: ingressgateway label to its metadata. If you omit this label, the AuthorizationPolicy configured earlier will not be applied.\nAdditional Resources A fully working example with Istio is also available on GitHub.\n","description":"Explains how to integrate heimdall with Istio Service Mesh.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://istio.io/\"\u003eIstio\u003c/a\u003e is an open-source service mesh that extends Kubernetes’ capabilities, providing a uniform way to observe, secure, and connect microservices. It also functions as a Kubernetes-based application gateway, using either its built-in \u003ca href=\"https://istio.io/latest/docs/concepts/traffic-management/#gateways\"\u003eIngress Gateway\u003c/a\u003e, the Kubernetes \u003ca href=\"https://istio.io/latest/docs/tasks/traffic-management/ingress/kubernetes-ingress/\"\u003eIngress\u003c/a\u003e, or the \u003ca href=\"https://gateway-api.sigs.k8s.io/\"\u003eGateway API\u003c/a\u003e resources for configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eA kubernetes cluster\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDeployed Istio (See \u003ca href=\"https://istio.io/latest/docs/setup/install/\"\u003ehere\u003c/a\u003e for installation options)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eheimdall installed and operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nTo allow heimdall communicating with services running in the mesh, add the certificate of the CA used by Istio to heimdall’s \u003ca href=\"/docs/operations/security/#_tls_trust_store\"\u003etrust store\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_integration_options\"\u003eIntegration Options\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTechnically, the integration works similarly to the \u003ca href=\"/guides/proxies/envoy/\"\u003eEnvoy\u003c/a\u003e setup by utilizing the \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e filter. This can be implemented in two ways:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003evia HTTP\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003evia gRPC (recommended)\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both approaches, the filter sends a request to an external gRPC or HTTP service (in this case, heimdall) to determine if the incoming HTTP request is authorized. If heimdall responds with a \u003ccode\u003e2xx\u003c/code\u003e status code, the request is forwarded to the upstream service. Otherwise, heimdall’s response is returned to the caller.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor Istio, this integration involves configuring an \u003ccode\u003eenvoyExtAuthzHttp\u003c/code\u003e or \u003ccode\u003eenvoyExtAuthzGrpc\u003c/code\u003e \u003ca href=\"https://istio.io/latest/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig-ExtensionProvider\"\u003eExtensionProvider\u003c/a\u003e for heimdall in the mesh configuration. The configured extension can then be enabled via an \u003ca href=\"https://istio.io/latest/docs/reference/config/security/authorization-policy/\"\u003e\u003ccode\u003eAuthorizationPolicy\u003c/code\u003e\u003c/a\u003e resource. Depending on its definition, heimdall can be used globally for all requests served through a particular gateway, or selectively for specific requests only.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe sections below explain how to achieve this for Istio’s Ingress Gateway, as well as using the Kubernetes Gateway API.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis guide assumes that Istio and heimdall are installed in the same cluster. If they are not, you will need to register heimdall in Istio’s internal service registry using a \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/service-entry/\"\u003e\u003ccode\u003eServiceEntry\u003c/code\u003e\u003c/a\u003e resource.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_common_configuration\"\u003eCommon Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_register_the_extension_provider\"\u003eRegister the Extension Provider\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs mentioned earlier, registering an extension provider in Istio’s mesh configuration is required. Follow these steps:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eEdit the mesh configuration: Run \u003ccode\u003ekubectl edit configmap istio -n istio-system\u003c/code\u003e to open the mesh configuration for editing.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAdd the \u003ccode\u003eextensionProvider\u003c/code\u003e configuration: Insert the following settings into the mesh configuration:\u003c/p\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ev1\u003c/span\u003e\n\u003cspan class=\"na\"\u003edata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emesh\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|-\u003c/span\u003e\n \u003cspan class=\"s\"\u003e# Add the following contents:\u003c/span\u003e\n \u003cspan class=\"s\"\u003eextensionProviders:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e- name: heimdall-ext-auth \u003c/span\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eenvoyExtAuthzGrpc: \u003c/span\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eservice: heimdall.heimdall.svc.cluster.local \u003c/span\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eport: \u0026#34;4455\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eheimdall-ext-auth\u003c/code\u003e is the name of our extension provider, which will be referenced later in the \u003ca href=\"https://istio.io/latest/docs/reference/config/security/authorization-policy/\"\u003e\u003ccode\u003eAuthorizationPolicy\u003c/code\u003e\u003c/a\u003e configuration.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWe’re using a gRPC based implementation here. However, since Istio does not automatically configure Envoy to use HTTP/2 for gRPC calls, it requires an additional \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/envoy-filter/\"\u003e\u003ccode\u003eEnvoyFilter\u003c/code\u003e\u003c/a\u003e resource. This appears to be a bug in Istio’s implementation.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHeimdall’s address within the cluster, which the extension provider will use for communication.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAlternatively, you can make use of \u003ccode\u003eenvoyExtAuthzHttp\u003c/code\u003e extension provider. In that case insert the following settings:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ev1\u003c/span\u003e\n\u003cspan class=\"na\"\u003edata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emesh\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|-\u003c/span\u003e\n \u003cspan class=\"s\"\u003e# Add the following contents:\u003c/span\u003e\n \u003cspan class=\"s\"\u003eextensionProviders:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e- name: heimdall-ext-auth\u003c/span\u003e\n \u003cspan class=\"s\"\u003eenvoyExtAuthzHttp:\u003c/span\u003e\n \u003cspan class=\"s\"\u003eservice: heimdall.heimdall.svc.cluster.local\u003c/span\u003e\n \u003cspan class=\"s\"\u003eport: \u0026#34;4455\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eincludeRequestHeadersInCheck: [ \u0026#34;authorization\u0026#34;, \u0026#34;cookie\u0026#34;, \u0026#34;accept\u0026#34;, \u0026#34;x-forwarded-for\u0026#34;, \u0026#34;x-forwarded-proto\u0026#34;, \u0026#34;x-forwarded-host\u0026#34; ] \u003c/span\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eheadersToUpstreamOnAllow: [ \u0026#34;authorization\u0026#34; ] \u003c/span\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eInclude further headers, you expect to make use of in your heimdall rules.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eInclude further headers, you expect to be set in your heimdall rules and which should be forwarded to the upstream service.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDeploy the following \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/envoy-filter/\"\u003e\u003ccode\u003eEnvoyFilter\u003c/code\u003e\u003c/a\u003e resource to correct the cluster configuration that Istio sets up for the heimdall service.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis is only required if you made use of the \u003ccode\u003eenvoyExtAuthzGrpc\u003c/code\u003e provider as shown above.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enetworking.istio.io/v1alpha3\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eEnvoyFilter\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp2-protocol-for-heimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-system\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfigPatches\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eapplyTo\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eCLUSTER\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003econtext\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGATEWAY\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoutbound|4455||heimdall.heimdall.svc.cluster.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003epatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eoperation\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eMERGE\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_extension_protocol_options\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eenvoy.extensions.upstreams.http.v3.HttpProtocolOptions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions\u003c/span\u003e\n \u003cspan class=\"s\"\u003eexplicit_http_config\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp2_protocol_options\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe namespace where the Istio control plane is deployed (the config root namespace). That way this filter is used each time envoy instance is created by Istio.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSpecifies that we want to apply the patch for a cluster\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSince we want this patch to be applied for gateways only, we limit the context accordingly\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is the actual config we would like to merge into the cluster definition to enable HTTP/2 support.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configure_additional_ca_certificates\"\u003eConfigure additional CA certificates\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis step is optional and only necessary if heimdall is configured to use TLS for inbound traffic.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIt is highly recommended to secure the communication between the Istio-managed gateway and heimdall. Instead of configuring heimdall to handle TLS directly, you can let Istio inject a proxy into heimdall’s pod to manage TLS termination. However, this approach introduces an additional network hop, which could negatively impact performance.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eInstruct Istio to trust heimdall’s certificate by applying the following \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/destination-rule/\"\u003e\u003ccode\u003eDestinationRule\u003c/code\u003e\u003c/a\u003e resource in the Istio root configuration namespace:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enetworking.istio.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eDestinationRule\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-system\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall.heimdall.svc.cluster.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003etrafficPolicy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSIMPLE\u003c/span\u003e\n \u003cspan class=\"na\"\u003esni\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall.heimdall.svc.cluster.local\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ecredentialName\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecacerts\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eIf \u003ccode\u003esni\u003c/code\u003e is not set, it defaults to the downstream HTTP \u003ccode\u003eHost\u003c/code\u003e or \u003ccode\u003eAuthority\u003c/code\u003e header, which will cause an error on the heimdall side because the name will not match the DNS entries in heimdall’s certificate.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe secret contains the certificate of the CA that issued heimdall’s certificate. Without this, Envoy won’t trust heimdall’s certificate. This secret must be available in every namespace where Istio creates a gateway.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_route_the_requests_through_heimdall\"\u003eRoute the requests through heimdall\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith the previous configuration in place, we can now instruct Istio to route the ingress traffic through heimdall first.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eCreate the following \u003ca href=\"https://istio.io/latest/docs/reference/config/security/authorization-policy/\"\u003e\u003ccode\u003eAuthorizationPolicy\u003c/code\u003e\u003c/a\u003e in Istio’s root configuration namespace:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esecurity.istio.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorizationPolicy\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-system\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eselector\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematchLabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eistio\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eingressgateway\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaction\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eCUSTOM\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprovider\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-ext-auth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis policy is specifically intended for gateways, excluding injected sidecars.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we reference the extension provider that was configured earlier.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe policy is set to apply universally, with no specific conditions, hence the empty rules.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith this configuration completed, you can proceed to deploy the necessary gateway resources.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_ingress_gateway_configuration\"\u003eIngress Gateway Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSimply create the Ingress \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/gateway/\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e resource and define the \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/virtual-service/\"\u003e\u003ccode\u003eVirtualService\u003c/code\u003e\u003c/a\u003e resources for your services according to your requirements. No further configuration is necessary.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_kubenetes_gateway_api\"\u003eKubenetes Gateway API\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs of this writing, Istio’s implementation of the Gateway API appears incomplete. It lacks the necessary \u003ccode\u003eRole\u003c/code\u003e and \u003ccode\u003eRoleBinding\u003c/code\u003e to access the \u003ccode\u003eSecret\u003c/code\u003e containing additional CA certificates. Without these, the Envoy instances cannot access the secret, preventing them from trusting heimdall’s certificate. To resolve this, apply the following resources in the namespace where the \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/gateway/#api-kind-gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e will be installed:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erbac.authorization.k8s.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRole\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egateway.istio.io/managed\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio.io-gateway-controller\u003c/span\u003e\n \u003cspan class=\"na\"\u003egateway.networking.k8s.io/gateway-name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n \u003cspan class=\"na\"\u003eistio\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eingressgateway\u003c/span\u003e\n \u003cspan class=\"na\"\u003eistio.io/gateway-name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw-istio\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eapiGroups\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eresources\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003esecrets\u003c/span\u003e\n \u003cspan class=\"na\"\u003everbs\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eget\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ewatch\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003elist\u003c/span\u003e\n\u003cspan class=\"nn\"\u003e---\u003c/span\u003e\n\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erbac.authorization.k8s.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRoleBinding\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egateway.istio.io/managed\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio.io-gateway-controller\u003c/span\u003e\n \u003cspan class=\"na\"\u003egateway.networking.k8s.io/gateway-name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n \u003cspan class=\"na\"\u003eistio\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eingressgateway\u003c/span\u003e\n \u003cspan class=\"na\"\u003eistio.io/gateway-name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw-istio\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n\u003cspan class=\"na\"\u003eroleRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapiGroup\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erbac.authorization.k8s.io\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRole\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw-istio\u003c/span\u003e\n\u003cspan class=\"na\"\u003esubjects\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eServiceAccount\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw-istio\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eChange the name of the service account accordingly; it follows the pattern \u003ccode\u003e\u0026lt;namespace\u0026gt;-istio\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNow, you can create the required \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/gateway/#api-kind-gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/gateway/#api-kind-httproute\"\u003e\u003ccode\u003eHTTPRoute\u003c/code\u003e\u003c/a\u003e resources for your service. When creating the \u003ccode\u003eGateway\u003c/code\u003e resource, ensure you add the \u003ccode\u003eistio: ingressgateway\u003c/code\u003e label to its metadata. If you omit this label, the \u003ca href=\"https://istio.io/latest/docs/reference/config/security/authorization-policy/\"\u003e\u003ccode\u003eAuthorizationPolicy\u003c/code\u003e\u003c/a\u003e configured earlier will not be applied.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA fully working example with Istio is also available on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Istio Service Mesh Integration","url":"/guides/proxies/istio/"},{"categories":null,"content":" NGINX is an HTTP and reverse proxy server which became famous as one of the fastest web servers out there, heimdall can be integrated with by making use of the ngx_http_auth_request_module. In such setup, NGINX delegates authentication and authorization to heimdall. If heimdall answers with a 2XX code, NGINX grants access and forwards the original request to the upstream service. If heimdall returns 401 or 403, the access is denied with the corresponding error code. Any other response code returned by heimdall is considered an error.\nPrerequisites Integration with NGINX requires heimdall being operated in Decision Operation Mode exposing its HTTP(s) endpoint.\nLimitations NGINX ngx_http_auth_request_module responsible for communication with external authentication \u0026amp; authorization services, like heimdall, has a few limitations. As written above, it only supports 200, 401 and 403 response codes. That means:\nYou’ll not be able to drive redirects from heimdall, as 3xx error codes will result in 500 error returned by NGINX. You can partially overcome that limitation by letting heimdall respond with a 401 or 403 error code and mapping that to a redirect in NGINX itself, e.g. like shown below. This definitely not DRY and will not allow you using multiple identity provider if you need to\n# nginx.conf ... # if the ext auth server, like heimdall returns `401 not authorized` # then forward the request to the error401 block error_page 401 = @error401; location @error401 { # redirect to the IdP for login return 302 https://your-idp-service/login; # you usually want your IdP to redirect back upon successful authentication # typically, you can achieve that by adding such query parameters like # return_to set to the value of the current request } If there is no matching rule on heimdall side, heimdall responds with 404 Not Found, which, as said above will be treated by NGINX as error. To avoid such situations, you can define a default rule, which is anyway recommended to have secure defaults\nVanilla NGINX Since NGINX is highly configurable and heimdall supports different integration options, you can use any of the configuration examples given below. All of these enable heimdall to build the URL of the protected backend server for rule matching purposes.\nIn most cases you must configure heimdall to trust your NGINX instances by setting trusted_proxies. Exceptions are described in the sections below.\nForward only the path and query information With this method you don’t set any headers. That means, you cannot rely on the used HTTP scheme, or the host and port in your rules. Here NGINX uses the same HTTP method, used in the original request to it and add the path and query to the path/query URL used for communication with heimdall. That integration method does not require the configuration of trusted_proxies in heimdall.\n# nginx.conf ... location / { auth_request /_auth; (1) auth_request_set $auth_cookie $upstream_http_set_cookie; (2) add_header Set-Cookie $auth_cookie; auth_request_set $authHeader0 $upstream_http_authorization; (3) proxy_set_header \u0026#39;Authorization\u0026#39; $authHeader0; # mitigate HTTPoxy Vulnerability # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ proxy_set_header Proxy \u0026#34;\u0026#34;; ... } location = /_auth { (4) internal; access_log off; proxy_method $request_method; (5) proxy_pass https://heimdall:4455$request_uri; (6) proxy_pass_request_body off; (7) proxy_set_header Content-Length \u0026#34;\u0026#34;; proxy_set_header Host $http_host; (8) } 1 Configures NGINX to forward every request to the internal /_auth endpoint (this is where the actual heimdall integration happens - see below). 2 When the response from heimdall returns, this and the next line set the Cookies set by heimdall in the response (whether you need this depends on your Contextualizers and Finalizers configuration) 3 When the response from heimdall returns, this and the next line set the Authorization header set by heimdall in the response (which header to set depends again on your Contextualizers and Finalizers configuration) 4 This is where the \u0026#34;magic\u0026#34; happens 5 Configure NGINX to use the HTTP method used by its client. Without this setting the implementation of proxy_path will use the HTTP GET method. 6 Configures NGINX to pass the request to heimdall and sets the request path and queries from the original request 7 Disables sending of the request body. If your heimdall rules make use of the body, you should set this to on and remove the next line. 8 Lets the NGINX setting the Host header, so it is accessible to heimdall. Forward all information in X-Forwarded-* headers With this method you set the X-Forwarded-Method, X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-Uri to let heimdall know the host, respectively domain url and the used HTTP method.\nCompared to the previous integration option, the configuration only differs in the definition of the internal /_auth endpoint. So, the example configuration is limited to that part only.\nProper configuration of trusted_proxies is mandatory if using this option. # nginx.conf ... location = /_auth { internal; proxy_pass https://heimdall:4455; (1) proxy_pass_request_body off; proxy_set_header Content-Length \u0026#34;\u0026#34;; proxy_set_header X-Forwarded-Method $request_method; (2) proxy_set_header X-Forwarded-Proto $scheme; (3) proxy_set_header X-Forwarded-Host $http_host; (4) proxy_set_header X-Forwarded-Uri $request_uri; (5) proxy_set_header X-Forwarded-For $remote_addr; } 1 Configures NGINX to pass the request to heimdall. 2 Let NGINX forward the used HTTP method to heimdall. 3 Let NGINX forward the used HTTP scheme to heimdall. 4 Let NGINX forward the used host to heimdall. 5 Let NGINX forward the used path and query parameter to heimdall. NGINX Ingress Controller Global Configuration Using X-Forwarded-* headers The configuration used in the example below requires proper configuration of trusted_proxies on heimdall side. Global configuration can be achieved by setting the following properties in controller ConfigMap. If you install the NGINX controller via the helm chart, you can add these properties under the controller.config property of your helm values.yaml file.\nglobal-auth-url: \u0026#34;https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34; (1) global-auth-response-headers: Authorization (2) global-auth-snippet: | (3) proxy_set_header X-Forwarded-Method $request_method; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-Uri $request_uri; 1 Configures the controller to use heimdall’s main service endpoint with \u0026lt;heimdall service name\u0026gt;, \u0026lt;namespace\u0026gt; and \u0026lt;port\u0026gt; depending on your configuration. 2 Let NGINX forward the Authorization header set by heimdall to the upstream service upon successful response. This configuration depends on your Contextualizers and Finalizers configuration. If not configured, NGINX will only react on Set-Cookie headers in responses from heimdall by default. 3 Configures the required headers to pass the information about the used HTTP scheme, host and port, request path and used query parameters to be forwarded to heimdall. Without that, heimdall will not be able extracting relevant information from the NGINX request as it does not support NGINX proprietary X-Original-Method and X-Original-Uri used by it for the same purposes. With that in place, you can simply use the standard Ingress resource, and the NGINX Ingress Controller will ensure, each request will be analyzed by heimdall first.\nThis will result in an NGINX configuration corresponding to the integration option, described in the Forward all information in X-Forwarded-* headers section.\nAlternative Configuration Alternatively, if you don’t want configuring trusted_proxies and do not rely on the used HTTP scheme, host and port in your rules, you can also use the location-snippet and the server-snippet to the ConfigMap of the NGINX Ingress Controller with values shown below.\nThis example is an exact copy of the configuration used in the very first integration option described above.\nlocation-snippet: | auth_request /_auth; auth_request_set $auth_cookie $upstream_http_set_cookie; add_header Set-Cookie $auth_cookie; auth_request_set $auth_header $upstream_http_authorization; proxy_set_header \u0026#39;Authorization\u0026#39; $auth_header; proxy_set_header Proxy \u0026#34;\u0026#34;; server-snippet: | location = /_auth { internal; access_log off; proxy_method $request_method; proxy_pass https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;$request_uri; proxy_pass_request_body off; proxy_set_header Content-Length \u0026#34;\u0026#34;; proxy_set_header Host $http_host; } As with the previous integration option, you can add these properties under the controller.config property of your helm values.yaml file if you install the NGINX Ingress Controller via helm.\nIntegration on Ingress Resource Level Using X-Forwarded-* headers One option to integrate heimdall with the NGINX Ingress Controller on the Ingress resource level is making use of the nginx.ingress.kubernetes.io/auth-url, nginx.ingress.kubernetes.io/auth-response-headers and the nginx.ingress.kubernetes.io/auth-snippet annotation as shown in the example below. This approach requires proper configuration of trusted_proxies on heimdall side. On NGINX Ingress Controller side you must allow the usage of nginx.ingress.kubernetes.io/auth-snippet (See also here).\nnginx.ingress.kubernetes.io/auth-url: \u0026#34;https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34; nginx.ingress.kubernetes.io/auth-response-headers: Authorization nginx.ingress.kubernetes.io/auth-snippet: | proxy_set_header X-Forwarded-Method $request_method; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-Uri $request_uri; # other annotations required Alternative Configuration Alternatively, if you don’t want configuring trusted_proxies and do not rely on the used HTTP scheme, host and port in your rules, you can also use the nginx.ingress.kubernetes.io/configuration-snippet and nginx.ingress.kubernetes.io/server-snippet annotations and use the configuration shown below.\nThis example is an exact copy of the configuration used in the very first integration option described above.\nnginx.ingress.kubernetes.io/configuration-snippet: | auth_request /_auth; auth_request_set $auth_cookie $upstream_http_set_cookie; add_header Set-Cookie $auth_cookie; auth_request_set $auth_header $upstream_http_authorization; proxy_set_header \u0026#39;Authorization\u0026#39; $auth_header; proxy_set_header Proxy \u0026#34;\u0026#34;; nginx.ingress.kubernetes.io/server-snippet: | location = /_auth { internal; access_log off; proxy_method $request_method; proxy_pass https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;$request_uri; proxy_pass_request_body off; proxy_set_header Content-Length \u0026#34;\u0026#34;; proxy_set_header Host $http_host; } # other annotations required Additional Resources Checkout the examples on GitHub for a working demo.\n","description":"This guide explains how to integrate heimdall with NGINX as well as with the NGINX Ingress Controller.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://nginx.org/\"\u003eNGINX\u003c/a\u003e is an HTTP and reverse proxy server which became famous as one of the fastest web servers out there, heimdall can be integrated with by making use of the \u003ca href=\"https://nginx.org/en/docs/http/ngx_http_auth_request_module.html\"\u003engx_http_auth_request_module\u003c/a\u003e. In such setup, NGINX delegates authentication and authorization to heimdall. If heimdall answers with a 2XX code, NGINX grants access and forwards the original request to the upstream service. If heimdall returns 401 or 403, the access is denied with the corresponding error code. Any other response code returned by heimdall is considered an error.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with NGINX requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e exposing its HTTP(s) endpoint.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_limitations\"\u003eLimitations\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNGINX \u003ca href=\"https://nginx.org/en/docs/http/ngx_http_auth_request_module.html\"\u003engx_http_auth_request_module\u003c/a\u003e responsible for communication with external authentication \u0026amp; authorization services, like heimdall, has a few limitations. As written above, it only supports 200, 401 and 403 response codes. That means:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eYou’ll not be able to drive redirects from heimdall, as 3xx error codes will result in 500 error returned by NGINX. You can partially overcome that limitation by letting heimdall respond with a 401 or 403 error code and mapping that to a redirect in NGINX itself, e.g. like shown below. This definitely not DRY and will not allow you using multiple identity provider if you need to\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"nginx\"\u003e\u003cspan class=\"c1\"\u003e# nginx.conf\u003c/span\u003e\n\u003cspan class=\"k\"\u003e...\u003c/span\u003e\n\n\u003cspan class=\"c1\"\u003e# if the ext auth server, like heimdall returns `401 not authorized`\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# then forward the request to the error401 block\u003c/span\u003e\n\u003cspan class=\"s\"\u003eerror_page\u003c/span\u003e \u003cspan class=\"mi\"\u003e401\u003c/span\u003e \u003cspan class=\"p\"\u003e=\u003c/span\u003e \u003cspan class=\"s\"\u003e@error401\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"k\"\u003elocation\u003c/span\u003e \u003cspan class=\"s\"\u003e@error401\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# redirect to the IdP for login\u003c/span\u003e\n \u003cspan class=\"kn\"\u003ereturn\u003c/span\u003e \u003cspan class=\"mi\"\u003e302\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://your-idp-service/login\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# you usually want your IdP to redirect back upon successful authentication\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# typically, you can achieve that by adding such query parameters like\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# return_to set to the value of the current request\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf there is no matching rule on heimdall side, heimdall responds with \u003ccode\u003e404 Not Found\u003c/code\u003e, which, as said above will be treated by NGINX as error. To avoid such situations, you can define a \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e, which is anyway recommended to have secure defaults\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_vanilla_nginx\"\u003eVanilla NGINX\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince NGINX is highly configurable and heimdall supports different integration options, you can use any of the configuration examples given below. All of these enable heimdall to build the URL of the protected backend server for rule matching purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn most cases you must configure heimdall to trust your NGINX instances by setting \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003e\u003ccode\u003etrusted_proxies\u003c/code\u003e\u003c/a\u003e. Exceptions are described in the sections below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_first_option\"\u003eForward only the path and query information\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith this method you don’t set any headers. That means, you cannot rely on the used HTTP scheme, or the host and port in your rules. Here NGINX uses the same HTTP method, used in the original request to it and add the path and query to the path/query URL used for communication with heimdall. That integration method does not require the configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e in heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"nginx\"\u003e\u003cspan class=\"c1\"\u003e# nginx.conf\u003c/span\u003e\n\u003cspan class=\"k\"\u003e...\u003c/span\u003e\n\n\u003cspan class=\"s\"\u003elocation\u003c/span\u003e \u003cspan class=\"n\"\u003e/\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eauth_request\u003c/span\u003e \u003cspan class=\"n\"\u003e/_auth\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eauth_request_set\u003c/span\u003e \u003cspan class=\"nv\"\u003e$auth_cookie\u003c/span\u003e \u003cspan class=\"nv\"\u003e$upstream_http_set_cookie\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eadd_header\u003c/span\u003e \u003cspan class=\"s\"\u003eSet-Cookie\u003c/span\u003e \u003cspan class=\"nv\"\u003e$auth_cookie\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eauth_request_set\u003c/span\u003e \u003cspan class=\"nv\"\u003e$authHeader0\u003c/span\u003e \u003cspan class=\"nv\"\u003e$upstream_http_authorization\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026#39;Authorization\u0026#39;\u003c/span\u003e \u003cspan class=\"nv\"\u003e$authHeader0\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# mitigate HTTPoxy Vulnerability\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eProxy\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003e...\u003c/span\u003e\n\u003cspan class=\"err\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"s\"\u003elocation\u003c/span\u003e \u003cspan class=\"p\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003e/_auth\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003einternal\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eaccess_log\u003c/span\u003e \u003cspan class=\"no\"\u003eoff\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_method\u003c/span\u003e \u003cspan class=\"nv\"\u003e$request_method\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_pass\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://heimdall:4455\u003c/span\u003e\u003cspan class=\"nv\"\u003e$request_uri\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_pass_request_body\u003c/span\u003e \u003cspan class=\"no\"\u003eoff\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eContent-Length\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eHost\u003c/span\u003e \u003cspan class=\"nv\"\u003e$http_host\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures NGINX to forward every request to the internal \u003ccode\u003e/_auth\u003c/code\u003e endpoint (this is where the actual heimdall integration happens - see below).\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWhen the response from heimdall returns, this and the next line set the Cookies set by heimdall in the response (whether you need this depends on your \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWhen the response from heimdall returns, this and the next line set the \u003ccode\u003eAuthorization\u003c/code\u003e header set by heimdall in the response (which header to set depends again on your \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is where the \u0026#34;magic\u0026#34; happens\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigure NGINX to use the HTTP method used by its client. Without this setting the implementation of \u003ccode\u003eproxy_path\u003c/code\u003e will use the HTTP GET method.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures NGINX to pass the request to heimdall and sets the request path and queries from the original request\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eDisables sending of the request body. If your heimdall rules make use of the body, you should set this to \u003ccode\u003eon\u003c/code\u003e and remove the next line.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLets the NGINX setting the \u003ccode\u003eHost\u003c/code\u003e header, so it is accessible to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_second_option\"\u003eForward all information in \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith this method you set the \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e and \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e to let heimdall know the host, respectively domain url and the used HTTP method.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCompared to the \u003ca href=\"#_first_option\"\u003eprevious integration\u003c/a\u003e option, the configuration only differs in the definition of the internal \u003ccode\u003e/_auth\u003c/code\u003e endpoint. So, the example configuration is limited to that part only.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nProper configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e is mandatory if using this option.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"nginx\"\u003e\u003cspan class=\"c1\"\u003e# nginx.conf\u003c/span\u003e\n\u003cspan class=\"k\"\u003e...\u003c/span\u003e\n\n\u003cspan class=\"s\"\u003elocation\u003c/span\u003e \u003cspan class=\"p\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003e/_auth\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kn\"\u003einternal\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_pass\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://heimdall:4455\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_pass_request_body\u003c/span\u003e \u003cspan class=\"no\"\u003eoff\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eContent-Length\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Forwarded-Method\u003c/span\u003e \u003cspan class=\"nv\"\u003e$request_method\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Forwarded-Proto\u003c/span\u003e \u003cspan class=\"nv\"\u003e$scheme\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Forwarded-Host\u003c/span\u003e \u003cspan class=\"nv\"\u003e$http_host\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Forwarded-Uri\u003c/span\u003e \u003cspan class=\"nv\"\u003e$request_uri\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Forwarded-For\u003c/span\u003e \u003cspan class=\"nv\"\u003e$remote_addr\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures NGINX to pass the request to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet NGINX forward the used HTTP method to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet NGINX forward the used HTTP scheme to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet NGINX forward the used host to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet NGINX forward the used path and query parameter to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_nginx_ingress_controller\"\u003eNGINX Ingress Controller\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h3\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_using_x_forwarded_headers\"\u003eUsing \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers\u003c/h4\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe configuration used in the example below requires proper configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e on heimdall side.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eGlobal configuration can be achieved by setting the following properties in controller \u003ccode\u003eConfigMap\u003c/code\u003e. If you install the NGINX controller via the helm chart, you can add these properties under the \u003ccode\u003econtroller.config\u003c/code\u003e property of your helm \u003ccode\u003evalues.yaml\u003c/code\u003e file.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eglobal-auth-url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://\u0026lt;heimdall\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eservice\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n\u003cspan class=\"na\"\u003eglobal-auth-response-headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n\u003cspan class=\"na\"\u003eglobal-auth-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Method $request_method;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Proto $scheme;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Host $http_host;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Uri $request_uri;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures the controller to use heimdall’s main service endpoint with \u003ccode\u003e\u0026lt;heimdall service name\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;namespace\u0026gt;\u003c/code\u003e and \u003ccode\u003e\u0026lt;port\u0026gt;\u003c/code\u003e depending on your configuration.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet NGINX forward the \u003ccode\u003eAuthorization\u003c/code\u003e header set by heimdall to the upstream service upon successful response. This configuration depends on\nyour \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration. If not configured, NGINX will only react on \u003ccode\u003eSet-Cookie\u003c/code\u003e headers in responses from heimdall by default.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures the required headers to pass the information about the used HTTP scheme, host and port, request path and used query parameters to be forwarded to heimdall.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWithout that, heimdall will not be able extracting relevant information from the NGINX request as it does not support NGINX proprietary \u003ccode\u003eX-Original-Method\u003c/code\u003e and \u003ccode\u003eX-Original-Uri\u003c/code\u003e used by it for the same purposes.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith that in place, you can simply use the standard \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/ingress/\"\u003e\u003ccode\u003eIngress\u003c/code\u003e\u003c/a\u003e resource, and the NGINX Ingress Controller will ensure, each request will be analyzed by heimdall first.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis will result in an NGINX configuration corresponding to the integration option, described in the \u003ca href=\"#_second_option\"\u003eForward all information in \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers\u003c/a\u003e section.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_alternative_configuration\"\u003eAlternative Configuration\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAlternatively, if you don’t want configuring \u003ccode\u003etrusted_proxies\u003c/code\u003e and do not rely on the used HTTP scheme, host and port in your rules, you can also use the \u003ccode\u003elocation-snippet\u003c/code\u003e and the \u003ccode\u003eserver-snippet\u003c/code\u003e to the \u003ccode\u003eConfigMap\u003c/code\u003e of the NGINX Ingress Controller with values shown below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example is an exact copy of the configuration used in the very first \u003ca href=\"#_first_option\"\u003eintegration option\u003c/a\u003e described above.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elocation-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request /_auth;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request_set $auth_cookie $upstream_http_set_cookie;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eadd_header Set-Cookie $auth_cookie;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request_set $auth_header $upstream_http_authorization;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header \u0026#39;Authorization\u0026#39; $auth_header;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Proxy \u0026#34;\u0026#34;;\u003c/span\u003e\n\u003cspan class=\"na\"\u003eserver-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003elocation = /_auth {\u003c/span\u003e\n \u003cspan class=\"s\"\u003einternal;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eaccess_log off;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_method $request_method;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_pass https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;$request_uri;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_pass_request_body off;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Content-Length \u0026#34;\u0026#34;;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Host $http_host;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with the previous integration option, you can add these properties under the \u003ccode\u003econtroller.config\u003c/code\u003e property of your helm \u003ccode\u003evalues.yaml\u003c/code\u003e file if you install the NGINX Ingress Controller via helm.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_integration_on_ingress_resource_level\"\u003eIntegration on \u003ccode\u003eIngress\u003c/code\u003e Resource Level\u003c/h3\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_using_x_forwarded_headers_2\"\u003eUsing \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOne option to integrate heimdall with the NGINX Ingress Controller on the \u003ccode\u003eIngress\u003c/code\u003e resource level is making use of the \u003ccode\u003enginx.ingress.kubernetes.io/auth-url\u003c/code\u003e, \u003ccode\u003enginx.ingress.kubernetes.io/auth-response-headers\u003c/code\u003e and the \u003ccode\u003enginx.ingress.kubernetes.io/auth-snippet\u003c/code\u003e annotation as shown in the example below. This approach requires proper configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e on heimdall side. On NGINX Ingress Controller side you must allow the usage of \u003ccode\u003enginx.ingress.kubernetes.io/auth-snippet\u003c/code\u003e (See also \u003ca href=\"https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#allow-snippet-annotations\"\u003ehere\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003enginx.ingress.kubernetes.io/auth-url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://\u0026lt;heimdall\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eservice\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003enginx.ingress.kubernetes.io/auth-response-headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n\u003cspan class=\"na\"\u003enginx.ingress.kubernetes.io/auth-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Method $request_method;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Proto $scheme;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Host $http_host;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Uri $request_uri;\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# other annotations required\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_alternative_configuration_2\"\u003eAlternative Configuration\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAlternatively, if you don’t want configuring \u003ccode\u003etrusted_proxies\u003c/code\u003e and do not rely on the used HTTP scheme, host and port in your rules, you can also use the \u003ccode\u003enginx.ingress.kubernetes.io/configuration-snippet\u003c/code\u003e and \u003ccode\u003enginx.ingress.kubernetes.io/server-snippet\u003c/code\u003e annotations and use the configuration shown below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example is an exact copy of the configuration used in the very first \u003ca href=\"#_first_option\"\u003eintegration option\u003c/a\u003e described above.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003enginx.ingress.kubernetes.io/configuration-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request /_auth;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request_set $auth_cookie $upstream_http_set_cookie;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eadd_header Set-Cookie $auth_cookie;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request_set $auth_header $upstream_http_authorization;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header \u0026#39;Authorization\u0026#39; $auth_header;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Proxy \u0026#34;\u0026#34;;\u003c/span\u003e\n\u003cspan class=\"na\"\u003enginx.ingress.kubernetes.io/server-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003elocation = /_auth {\u003c/span\u003e\n \u003cspan class=\"s\"\u003einternal;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eaccess_log off;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_method $request_method;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_pass https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;$request_uri;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_pass_request_body off;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Content-Length \u0026#34;\u0026#34;;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Host $http_host;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# other annotations required\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCheckout the examples on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e for a working demo.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"NGINX Integration","url":"/guides/proxies/nginx/"},{"categories":null,"content":" Traefik Proxy is a modern HTTP proxy and load balancer for microservices, heimdall can be integrated with via the ForwardAuth Middleware. If heimdall answers with a 2XX code, traefik grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\nPrerequisites Integration with traefik requires heimdall being operated in Decision Operation Mode.\nTraefik makes use of X-Forwarded-* HTTP headers to forward the HTTP method, protocol, host, etc. to the ForwardAuth middleware. By default, heimdall does not trust those. To allow heimdall making use of such headers, you must configure trusted proxies in heimdall’s main service configuration to contain the IPs or networks of your traefik instances. For test purposes, you can set it to \u0026#34;0.0.0.0/0\u0026#34;, which would basically disable the check and let heimdall trust requests from any source.\nTraefik can be configured statically, but also load dynamic configuration from many sources managed by so-called providers. The following sections describe how to integrate with heimdall using some of them.\nGlobal Configuration To let Traefik forward all incoming requests to heimdall, there is a need\nto configure the ForwardAuth middleware, and\nto add it to the list of middlewares that are prepended by default to the list of middlewares of each router associated to a named entry point.\nRegular Deployment If you are using Traefik outside of kubernetes, the above can be achieved by the following static configuration\nentryPoints: web: address: \u0026#34;:8080\u0026#34; middlewares: (1) - heimdall http: middlewares: heimdall: (2) forwardAuth: (3) address: \u0026#34;https://heimdall:4455\u0026#34; (4) authResponseHeaders: - Authorization (5) 1 The list of default middlewares. Here only the middleware named \u0026#34;heimdall\u0026#34; is included. That way, traefik will use this middleware for each and every request. 2 The definition of the middleware named \u0026#34;heimdall\u0026#34; 3 which is of type forwardAuth 4 Configures this middleware to forward requests to a service available under \u0026#34;heimdall\u0026#34; DNS name 5 Configures this middleware to forward the Authorization header from heimdall’s response to the upstream service Kubernetes Deployment If you are using Traefik as Ingress Controller or as Gateway API implementation in your kubernetes cluster, the required configuration is slightly different. The configuration of the entry point(s) stays the same, but the middleware needs to be deployed as a custom resource.\nHere an example for a Middleware custom resource:\napiVersion: traefik.io/v1alpha1 kind: Middleware metadata: (1) name: heimdall namespace: heimdall spec: forwardAuth: (2) address: \u0026#34;https://heimdall.heimdall.svc.cluster.local:4455\u0026#34; (3) authResponseHeaders: (4) - Authorization 1 The name and the namespace of the middleware. Both are set to heimdall here 2 The type of the middleware, which is of type forwardAuth 3 Configures this middleware to forward requests to the heimdall service. Here, the corresponding Service is named heimdall and is also located in the namespace named heimdall. 4 Configures this middleware to forward the Authorization header from heimdall’s response to the upstream service How to add this middleware to the default middleware list of a particular endpoint depends on the method used to install Traefik. If helm is used, you can configure that list by making use of the following values.yaml file:\nproviders: kubernetesCRD: enabled: true (1) ports: web: (2) middlewares: - heimdall-heimdall@kubernetescrd (3) websecure: (4) middlewares: - heimdall-heimdall@kubernetescrd 1 To let traefik load Middleware resources, like defined above, traefik’s kubernetesCRD provider must be enabled. Typically, it is enabled by default. 2 Traefik’s helm chart defines two entry points web for HTTP traffic and websecure for HTTPS traffic. Here we configure the web endpoint to use our middleware 3 Reference to the Middleware resource, defined above. The general structure is \u0026lt;middleware name\u0026gt;-\u0026lt;middleware namespace\u0026gt;@\u0026lt;provider\u0026gt;. Since our middleware resource is loaded by the kubernetescrd provider, resides in the heimdall namespace, and is named heimdall, the reference heimdall-heimdall@kubernetescrd is used. 4 Here we configure the websecure endpoint, which, as written above, is configured via helm chart for HTTPS traffic. The actual configuration is identical to the configuration for the web endpoint. Route-based Configuration with Docker The integration option, described here makes use of the Docker Provider for configuration discovery.\nThe following docker-compose.yaml file shows a minimal required configuration.\nservices: proxy: image: traefik:2.11.0 ports: - \u0026#34;9090:9090\u0026#34; command: \u0026gt; --providers.docker=true (1) --providers.docker.exposedbydefault=false --entryPoints.http.address=\u0026#34;:9090\u0026#34; volumes: - \u0026#34;/var/run/docker.sock:/var/run/docker.sock:ro\u0026#34; (2) # other config options labels: # other labels - traefik.http.middlewares.heimdall.forwardauth.address=https://heimdall:4455 (3) - traefik.http.middlewares.heimdall.forwardauth.authResponseHeaders=Authorization (4) heimdall: image: dadrus/heimdall:dev # further config upstream: # image and config of your upstream service labels: # other labels - traefik.http.routers.upstream.middlewares=heimdall (5) 1 This and the next line configures the docker provider 2 The docker provider reads the configuration from labels of the services and requires access to the docker socket for this purpose 3 Configuration of the ForwardAuth middleware to forward incoming requests to heimdall. The name of middleware is set to \u0026#34;heimdall\u0026#34; here. 4 Configuration of the ForwardAuth middleware to forward the Authorization header from heimdall’s response to the upstream service 5 Configuration of the required middlewares on the route level of a particular service. Here only the middleware named \u0026#34;heimdall\u0026#34; is referenced. Without that label, traefik will not forward requests to heimdall before routing them to that upstream service. Traefik as Ingress Controller If you have Traefik as Ingress Controller in your Kubernetes cluster, you can simply integrate heimdall globally as descibed in Global Configuration chapter above and make use of the standard Ingress resource.\nIf you are using traefik’s proprietary IngressRoute custom resource instead of kubernetes standard Ingress one, you can also reference the Middleware resource locally. This option is shown in the snippet below.\napiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: (1) name: demo-app namespace: demo spec: entryPoints: - web (2) routes: - kind: Rule match: Host(`demo-app.local`) \u0026amp;\u0026amp; PathPrefix(`/`) middlewares: (3) - name: heimdall namespace: heimdall services: (4) - kind: Service name: demo-app namespace: demo port: app-port 1 metadata, like name and the namespace of the IngressRoute resource 2 The traefik entry points to attach this resource to. Here only web entry point is referenced 3 List of the middlewares to be applied. Here the Middleware named heimdall in the namespace heimdall is referenced. By default, IngressRoute resources are not allowed to reference resources in namespaces different from the own namespace. If your Middleware resource, like also shown here, is deployed in another namespace, you have to allow that. If traefik is installed via helm, it can be achieved by setting providers.kubernetesCRD.allowCrossNamespace to true (See also here). 4 The reference to the Service, the requests should be forwarded to. Traefik as Gateway API implementation If you have Traefik as Gateway API implementation in your Kubernetes cluster, you can simply integrate heimdall globally as descibed in Global Configuration chapter above and make use of the standard HTTPRoute resource.\nAdditional Resources A fully working example with Traefik is shown in the Protect an Application quickstart and is also available on GitHub.\n","description":"This guide explains how to integrate heimdall with Traefik Proxy.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://doc.traefik.io/traefik/\"\u003eTraefik Proxy\u003c/a\u003e is a modern HTTP proxy and load balancer for microservices, heimdall can be integrated with via the \u003ca href=\"https://doc.traefik.io/traefik/middlewares/http/forwardauth/\"\u003eForwardAuth Middleware\u003c/a\u003e. If heimdall answers with a 2XX code, traefik grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with traefik requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTraefik makes use of \u003ccode\u003eX-Forwarded-*\u003c/code\u003e HTTP headers to forward the HTTP method, protocol, host, etc. to the ForwardAuth middleware. By default, heimdall does not trust those. To allow heimdall making use of such headers, you must configure \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003etrusted proxies\u003c/a\u003e in heimdall’s main service configuration to contain the IPs or networks of your traefik instances. For test purposes, you can set it to \u0026#34;0.0.0.0/0\u0026#34;, which would basically disable the check and let heimdall trust requests from any source.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTraefik can be configured statically, but also load dynamic configuration from many sources managed by so-called providers. The following sections describe how to integrate with heimdall using some of them.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo let Traefik forward all incoming requests to heimdall, there is a need\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eto configure the \u003ca href=\"https://doc.traefik.io/traefik/middlewares/http/forwardauth/\"\u003eForwardAuth\u003c/a\u003e middleware, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eto add it to the list of \u003ca href=\"https://doc.traefik.io/traefik/routing/entrypoints/#middlewares\"\u003emiddlewares\u003c/a\u003e that are prepended by default to the list of middlewares of each router associated to a named entry point.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_regular_deployment\"\u003eRegular Deployment\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you are using Traefik outside of kubernetes, the above can be achieved by the following static configuration\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eentryPoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eweb\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e:8080\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003emiddlewares\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003ehttp\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emiddlewares\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eforwardAuth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://heimdall:4455\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eauthResponseHeaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe list of default middlewares. Here only the middleware named \u0026#34;heimdall\u0026#34; is included. That way, traefik will use this middleware for each and every request.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe definition of the middleware named \u0026#34;heimdall\u0026#34;\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003ewhich is of type \u003ca href=\"https://doc.traefik.io/traefik/middlewares/http/forwardauth/\"\u003e\u003ccode\u003eforwardAuth\u003c/code\u003e\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures this middleware to forward requests to a service available under \u0026#34;heimdall\u0026#34; DNS name\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures this middleware to forward the \u003ccode\u003eAuthorization\u003c/code\u003e header from heimdall’s response to the upstream service\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_kubernetes_deployment\"\u003eKubernetes Deployment\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you are using Traefik as \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/\"\u003eIngress Controller\u003c/a\u003e or as \u003ca href=\"https://gateway-api.sigs.k8s.io/\"\u003eGateway API\u003c/a\u003e implementation in your kubernetes cluster, the required configuration is slightly different. The configuration of the entry point(s) stays the same, but the middleware needs to be deployed as a custom resource.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere an example for a \u003ca href=\"https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/#kind-middleware\"\u003e\u003ccode\u003eMiddleware\u003c/code\u003e\u003c/a\u003e custom resource:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.io/v1alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eMiddleware\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforwardAuth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://heimdall.heimdall.svc.cluster.local:4455\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eauthResponseHeaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe name and the namespace of the middleware. Both are set to \u003ccode\u003eheimdall\u003c/code\u003e here\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe type of the middleware, which is of type \u003ca href=\"https://doc.traefik.io/traefik/middlewares/http/forwardauth/\"\u003e\u003ccode\u003eforwardAuth\u003c/code\u003e\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures this middleware to forward requests to the heimdall service. Here, the corresponding \u003ccode\u003eService\u003c/code\u003e is named \u003ccode\u003eheimdall\u003c/code\u003e and is also located in the namespace named \u003ccode\u003eheimdall\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures this middleware to forward the \u003ccode\u003eAuthorization\u003c/code\u003e header from heimdall’s response to the upstream service\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow to add this middleware to the default middleware list of a particular endpoint depends on the method used to install Traefik. If helm is used, you can configure that list by making use of the following \u003ccode\u003evalues.yaml\u003c/code\u003e file:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eproviders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekubernetesCRD\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n\n\u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eweb\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003emiddlewares\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-heimdall@kubernetescrd\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ewebsecure\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003emiddlewares\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-heimdall@kubernetescrd\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eTo let traefik load \u003ccode\u003eMiddleware\u003c/code\u003e resources, like defined above, traefik’s \u003ccode\u003ekubernetesCRD\u003c/code\u003e provider must be enabled. Typically, it is enabled by default.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eTraefik’s helm chart defines two entry points \u003ccode\u003eweb\u003c/code\u003e for HTTP traffic and \u003ccode\u003ewebsecure\u003c/code\u003e for HTTPS traffic. Here we configure the \u003ccode\u003eweb\u003c/code\u003e endpoint to use our middleware\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eReference to the \u003ccode\u003eMiddleware\u003c/code\u003e resource, defined above. The general structure is \u003ccode\u003e\u0026lt;middleware name\u0026gt;-\u0026lt;middleware namespace\u0026gt;@\u0026lt;provider\u0026gt;\u003c/code\u003e. Since our middleware resource is loaded by the \u003ccode\u003ekubernetescrd\u003c/code\u003e provider, resides in the \u003ccode\u003eheimdall\u003c/code\u003e namespace, and is named \u003ccode\u003eheimdall\u003c/code\u003e, the reference \u003ccode\u003eheimdall-heimdall@kubernetescrd\u003c/code\u003e is used.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we configure the \u003ccode\u003ewebsecure\u003c/code\u003e endpoint, which, as written above, is configured via helm chart for HTTPS traffic. The actual configuration is identical to the configuration for the \u003ccode\u003eweb\u003c/code\u003e endpoint.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_route_based_configuration_with_docker\"\u003eRoute-based Configuration with Docker\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe integration option, described here makes use of the \u003ca href=\"https://doc.traefik.io/traefik/providers/docker/\"\u003eDocker Provider\u003c/a\u003e for configuration discovery.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following \u003ccode\u003edocker-compose.yaml\u003c/code\u003e file shows a minimal required configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eproxy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik:2.11.0\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e9090:9090\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--providers.docker=true \u003c/span\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"s\"\u003e--providers.docker.exposedbydefault=false\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--entryPoints.http.address=\u0026#34;:9090\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e/var/run/docker.sock:/var/run/docker.sock:ro\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"c1\"\u003e# other config options\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other labels\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.middlewares.heimdall.forwardauth.address=https://heimdall:4455\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.middlewares.heimdall.forwardauth.authResponseHeaders=Authorization\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edadrus/heimdall:dev\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# further config\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eupstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# image and config of your upstream service\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other labels\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.routers.upstream.middlewares=heimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis and the next line configures the docker provider\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe docker provider reads the configuration from labels of the services and requires access to the docker socket for this purpose\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfiguration of the \u003ca href=\"https://doc.traefik.io/traefik/middlewares/http/forwardauth/\"\u003eForwardAuth\u003c/a\u003e middleware to forward incoming requests to heimdall. The name of middleware is set to \u0026#34;heimdall\u0026#34; here.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfiguration of the ForwardAuth middleware to forward the \u003ccode\u003eAuthorization\u003c/code\u003e header from heimdall’s response to the upstream service\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfiguration of the required middlewares on the route level of a particular service. Here only the middleware named \u0026#34;heimdall\u0026#34; is referenced. Without that label, traefik will not forward requests to heimdall before routing them to that upstream service.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_traefik_as_ingress_controller\"\u003eTraefik as Ingress Controller\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you have Traefik as Ingress Controller in your Kubernetes cluster, you can simply integrate heimdall globally as descibed in \u003ca href=\"#_global_configuration\"\u003eGlobal Configuration\u003c/a\u003e chapter above and make use of the standard \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/ingress/\"\u003eIngress resource\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you are using traefik’s proprietary \u003ca href=\"https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/#kind-ingressroute\"\u003e\u003ccode\u003eIngressRoute\u003c/code\u003e\u003c/a\u003e custom resource instead of kubernetes standard \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/ingress/\"\u003e\u003ccode\u003eIngress\u003c/code\u003e\u003c/a\u003e one, you can also reference the \u003ca href=\"https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/#kind-middleware\"\u003e\u003ccode\u003eMiddleware\u003c/code\u003e\u003c/a\u003e resource locally. This option is shown in the snippet below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.io/v1alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eIngressRoute\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo-app\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eentryPoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eweb\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRule\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eHost(`demo-app.local`) \u0026amp;\u0026amp; PathPrefix(`/`)\u003c/span\u003e\n \u003cspan class=\"na\"\u003emiddlewares\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eService\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo-app\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapp-port\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003emetadata\u003c/code\u003e, like name and the namespace of the \u003ccode\u003eIngressRoute\u003c/code\u003e resource\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe traefik entry points to attach this resource to. Here only \u003ccode\u003eweb\u003c/code\u003e entry point is referenced\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eList of the middlewares to be applied. Here the \u003ccode\u003eMiddleware\u003c/code\u003e named \u003ccode\u003eheimdall\u003c/code\u003e in the namespace \u003ccode\u003eheimdall\u003c/code\u003e is referenced.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nBy default, \u003ccode\u003eIngressRoute\u003c/code\u003e resources are not allowed to reference resources in namespaces different from the own namespace. If your \u003ccode\u003eMiddleware\u003c/code\u003e resource, like also shown here, is deployed in another namespace, you have to allow that. If traefik is installed via helm, it can be achieved by setting \u003ccode\u003eproviders.kubernetesCRD.allowCrossNamespace\u003c/code\u003e to \u003ccode\u003etrue\u003c/code\u003e (See also \u003ca href=\"https://doc.traefik.io/traefik/providers/kubernetes-crd/#allowcrossnamespace\"\u003ehere\u003c/a\u003e).\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe reference to the \u003ccode\u003eService\u003c/code\u003e, the requests should be forwarded to.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_traefik_as_gateway_api_implementation\"\u003eTraefik as Gateway API implementation\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you have Traefik as \u003ca href=\"https://gateway-api.sigs.k8s.io/\"\u003eGateway API\u003c/a\u003e implementation in your Kubernetes cluster, you can simply integrate heimdall globally as descibed in \u003ca href=\"#_kubernetes_deployment\"\u003eGlobal Configuration\u003c/a\u003e chapter above and make use of the standard \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/httproute\"\u003e\u003ccode\u003eHTTPRoute\u003c/code\u003e\u003c/a\u003e resource.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA fully working example with Traefik is shown in the \u003ca href=\"/docs/getting_started/protect_an_app/\"\u003eProtect an Application\u003c/a\u003e quickstart and is also available on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Traefik Proxy Integration","url":"/guides/proxies/traefik/"},{"categories":null,"content":" The Protect an Application quickstart guide, describing the steps required to protect an application with heimdall, shows already how OPA can be used with heimdall. This document provides some further examples.\nExample 1: Sharing Service Imagine you have a sharing service, e.g. to let friends share all their photos with each other and the API looks roughly as follows:\nGET /\u0026lt;user\u0026gt;/photos returns all the photos of the user either to the owner of the photo collection itself or to its friends.\nTo achieve this using OPA, we would need something like the following Rego policy:\npackage share_photos default allow = false # user is owner. that is, the value of first path # fragment is equal to the identified user allow { split(input.path, \u0026#34;/\u0026#34;)[1] == input.user } # user is friend. that is, the user referenced by the # first path fragment has the identified user in its friends list allow { data.friends[split(input.path, \u0026#34;/\u0026#34;)[1]][_] == input.user } It expects two pieces of information in the payload to the OPA instance:\nthe actual user, making the request and\nthe path to witch the request is made\nSo something like this: { \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;alice\u0026#34;, \u0026#34;path\u0026#34;: \u0026#34;bob/photos\u0026#34; } }. Since the Rego policy defined above returns just true or false, the corresponding response from the OPA endpoint would be { \u0026#34;result\u0026#34;: true } or { \u0026#34;result\u0026#34;: false }. Given this and assuming the above policy can be used by making requests to https://opa.local/v1/data/share_photos/policy/allow, the configuration of the Remote Authorizer would look like follows:\nid: photos_access type: remote config: endpoint: url: https://opa.local/v1/data/share_photos/policy/allow payload: | { \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }}, \u0026#34;path\u0026#34;: {{ quote .RequestURL.Path }} } } expressions: - expression: | Payload.result == true Here the entire authorization happens within heimdall and is completely outsourced from the business logic of our sharing service.\nExample 2: Membership Verification Imagine you have a billing service, which requires information about the membership of a user to different groups, which represent different subscription options for you entire offering. Depending on this information your service would create invoices with different amounts. The imaginary API of that service could look like follows:\nPOST /create_invoice to invoice the identified user.\nYou could perform the required query to OPA entirely in your service and use the retrieved group memberships then. Alternatively, you could outsource the communication to OPA to heimdall and deal only with the group membership information in your service. Compared to the Sharing Service example, this time heimdall would not perform any authorization, but rather enrich the subject information with further information. This way, we’re not going to use a Authorizer, but a Generic Contextualizer instead. As with Sharing Service example, there is a need for a Rego policy, which could look like this:\npackage invoice groups_graph[data.groups[subject].name] = edges { edges := data.groups[subject].member_of } member_of_groups[subject] = groups { groups_graph[subject] groups := graph.reachable(groups_graph, {subject}) } groups { member_of_groups[input.user][_] } It expects just one piece of information, namely the actual user, making the request. So something like this: { \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;alice\u0026#34; } }. Since the Rego policy defined above returns a list of groups, the corresponding response from the OPA endpoint would be { \u0026#34;result\u0026#34;: [\u0026#34;group1\u0026#34;, \u0026#34;group2\u0026#34;] }. Given this and assuming the above policy can be used by making requests to https://opa.local/v1/data/invoice/policy/groups and the authentication to that endpoint requires basic authentication, the configuration of the Generic Contextualizer would look like follows:\nid: billing_contextualizer type: generic config: endpoint: url: https://opa.local/v1/data/invoice/policy/groups auth: type: basic_auth config: user: MyOpaUser password: SuperSecretPassword payload: | { \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }} } } Upon successful execution of the corresponding request, the response from the OPA endpoint will be stored in the Outputs[\u0026#34;billing_contextualizer\u0026#34;] field. That way, you can use that information in a Finalizer to forward the group membership to the billing service API.\n","description":"This guide provides examples on how to integrate heimdall with the Open Policy Agent.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"/docs/getting_started/protect_an_app/\"\u003eProtect an Application\u003c/a\u003e quickstart guide, describing the steps required to protect an application with heimdall, shows already how \u003ca href=\"https://www.openpolicyagent.org/\"\u003eOPA\u003c/a\u003e can be used with heimdall. This document provides some further examples.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_example_1_sharing_service\"\u003eExample 1: Sharing Service\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you have a sharing service, e.g. to let friends share all their photos with each other and the API looks roughly as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eGET /\u0026lt;user\u0026gt;/photos\u003c/code\u003e returns all the photos of the user either to the owner of the photo collection itself or to its friends.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo achieve this using OPA, we would need something like the following \u003ca href=\"https://www.openpolicyagent.org/docs/latest/policy-language/\"\u003eRego\u003c/a\u003e policy:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"rego\"\u003e\u003cspan class=\"ow\"\u003epackage\u003c/span\u003e \u003cspan class=\"n\"\u003eshare_photos\u003c/span\u003e\n\n\u003cspan class=\"ow\"\u003edefault\u003c/span\u003e \u003cspan class=\"n\"\u003eallow\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n\n\u003cspan class=\"c1\"\u003e# user is owner. that is, the value of first path\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# fragment is equal to the identified user\u003c/span\u003e\n\u003cspan class=\"n\"\u003eallow\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"n\"\u003esplit\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003epath\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)[\u003c/span\u003e\u003cspan class=\"m\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003euser\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"c1\"\u003e# user is friend. that is, the user referenced by the\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# first path fragment has the identified user in its friends list\u003c/span\u003e\n\u003cspan class=\"n\"\u003eallow\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"n\"\u003edata\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003efriends\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003esplit\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003epath\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)[\u003c/span\u003e\u003cspan class=\"m\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e]][\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003euser\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIt expects two pieces of information in the payload to the OPA instance:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ethe actual user, making the request and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe path to witch the request is made\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSo something like this: \u003ccode\u003e{ \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;alice\u0026#34;, \u0026#34;path\u0026#34;: \u0026#34;bob/photos\u0026#34; } }\u003c/code\u003e. Since the Rego policy defined above returns just \u003ccode\u003etrue\u003c/code\u003e or \u003ccode\u003efalse\u003c/code\u003e, the corresponding response from the OPA endpoint would be \u003ccode\u003e{ \u0026#34;result\u0026#34;: true }\u003c/code\u003e or \u003ccode\u003e{ \u0026#34;result\u0026#34;: false }\u003c/code\u003e. Given this and assuming the above policy can be used by making requests to \u003ccode\u003ehttps://opa.local/v1/data/share_photos/policy/allow\u003c/code\u003e, the configuration of the \u003ca href=\"/docs/mechanisms/authorizers/#_remote\"\u003eRemote Authorizer\u003c/a\u003e would look like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ephotos_access\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://opa.local/v1/data/share_photos/policy/allow\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{ \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }}, \u0026#34;path\u0026#34;: {{ quote .RequestURL.Path }} } }\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.result == true\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere the entire authorization happens within heimdall and is completely outsourced from the business logic of our sharing service.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_example_2_membership_verification\"\u003eExample 2: Membership Verification\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you have a billing service, which requires information about the membership of a user to different groups, which represent different subscription options for you entire offering. Depending on this information your service would create invoices with different amounts. The imaginary API of that service could look like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ePOST /create_invoice\u003c/code\u003e to invoice the identified user.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou could perform the required query to OPA entirely in your service and use the retrieved group memberships then. Alternatively, you could outsource the communication to OPA to heimdall and deal only with the group membership information in your service. Compared to the \u003ca href=\"#_example_1_sharing_service\"\u003eSharing Service\u003c/a\u003e example, this time heimdall would not perform any authorization, but rather enrich the subject information with further information. This way, we’re not going to use a \u003ca href=\"/docs/mechanisms/authorizers/\"\u003eAuthorizer\u003c/a\u003e, but a \u003ca href=\"/docs/mechanisms/contextualizers/#_generic\"\u003eGeneric Contextualizer\u003c/a\u003e instead. As with \u003ca href=\"#_example_1_sharing_service\"\u003eSharing Service\u003c/a\u003e example, there is a need for a \u003ca href=\"https://www.openpolicyagent.org/docs/latest/policy-language/\"\u003eRego\u003c/a\u003e policy, which could look like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"rego\"\u003e\u003cspan class=\"ow\"\u003epackage\u003c/span\u003e \u003cspan class=\"n\"\u003einvoice\u003c/span\u003e\n\n\u003cspan class=\"n\"\u003egroups_graph\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003edata\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003egroups\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003esubject\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"n\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eedges\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"n\"\u003eedges\u003c/span\u003e \u003cspan class=\"o\"\u003e:=\u003c/span\u003e \u003cspan class=\"n\"\u003edata\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003egroups\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003esubject\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"n\"\u003emember_of\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"n\"\u003emember_of_groups\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003esubject\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003egroups\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"n\"\u003egroups_graph\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003esubject\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n \u003cspan class=\"n\"\u003egroups\u003c/span\u003e \u003cspan class=\"o\"\u003e:=\u003c/span\u003e \u003cspan class=\"n\"\u003egraph\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ereachable\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003egroups_graph\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"n\"\u003esubject\u003c/span\u003e\u003cspan class=\"p\"\u003e})\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"n\"\u003egroups\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"n\"\u003emember_of_groups\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003euser\u003c/span\u003e\u003cspan class=\"p\"\u003e][\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIt expects just one piece of information, namely the actual user, making the request. So something like this: \u003ccode\u003e{ \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;alice\u0026#34; } }\u003c/code\u003e. Since the Rego policy defined above returns a list of groups, the corresponding response from the OPA endpoint would be \u003ccode\u003e{ \u0026#34;result\u0026#34;: [\u0026#34;group1\u0026#34;, \u0026#34;group2\u0026#34;] }\u003c/code\u003e. Given this and assuming the above policy can be used by making requests to \u003ccode\u003ehttps://opa.local/v1/data/invoice/policy/groups\u003c/code\u003e and the authentication to that endpoint requires basic authentication, the configuration of the \u003ca href=\"/docs/mechanisms/contextualizers/#_generic\"\u003eGeneric Contextualizer\u003c/a\u003e would look like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebilling_contextualizer\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://opa.local/v1/data/invoice/policy/groups\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eMyOpaUser\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSuperSecretPassword\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{ \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }} } }\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUpon successful execution of the corresponding request, the response from the OPA endpoint will be stored in the \u003ccode\u003eOutputs[\u0026#34;billing_contextualizer\u0026#34;]\u003c/code\u003e field. That way, you can use that information in a \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizer\u003c/a\u003e to forward the group membership to the billing service API.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","Authorization Services"],"tags":null,"title":"Integration with OPA","url":"/guides/authz/opa/"},{"categories":null,"content":" OpenFGA is inspired by Google’s Zanzibar, Google’s Relationship Based Access Control system and allows easily implementing authorization for any kind of application relying on Role-Based Access Control with additional Attribute-Based Access Control capabilities.\nThis guide is based on the OpenFGA’s official Getting Started guide and highlights the relevant differences. It mimics a RESTful document management API, allowing listing, creating, reading, updating, and deleting documents. The API consists of two endpoints:\n/document/\u0026lt;id\u0026gt; with id being the id of the document and the HTTP verbs reflecting the actual operations. E.g. a GET /document/1234 request should read the document with the id 1234.\n/documents which supports the HTTP GET verb only and allows the user to list the documents it can access.\nThe identity of the user will be taken from a JWT.\nEven this guide addresses OpenFGA, it actually covers integration with any ReBAC system, be it Ory’s Keto, SpiceDB from AuthZed, or any other system inspired by Google’s Zanzibar. Prerequisites To be able to follow this guide, you’ll need the following tools installed locally:\nDocker,\ndocker-compose, and\na text editor of your choice.\nConfigure the Base Setup Create a directory in which we’re going to create further directories and files required for the setup and switch to it.\nCreate a directory named rules. We’ll add the heimdall rule to it after our setup is started.\nCreate a docker-compose.yaml file with the following contents\nservices: heimdall: (1) image: dadrus/heimdall:dev container_name: heimdall ports: - \u0026#34;9090:4455\u0026#34; volumes: - ./heimdall-config.yaml:/etc/heimdall/config.yaml:ro - ./rules:/etc/heimdall/rules:ro - ./signer.pem:/etc/heimdall/signer.pem:ro command: serve proxy -c /etc/heimdall/config.yaml --insecure upstream: (2) image: containous/whoami:latest container_name: upstream command: - --port=8081 openfga: (3) image: openfga/openfga:latest container_name: openfga command: run ports: - \u0026#34;8080:8080\u0026#34; idp: (4) image: nginx:1.25.4 volumes: - ./idp.nginx:/etc/nginx/nginx.conf:ro - ./jwks.json:/var/www/nginx/jwks.json:ro 1 These lines configure heimdall to use a config file, we’re going to configure next and a rule directory, we’ll add our rules to. We’re using the --insecure flag here to simplify our setup, which disables enforcement of some security settings you can learn about more here. 2 Here, we define the \u0026#34;upstream\u0026#34; service, which just echoes back everything it receives. 3 And these lines configure our OpenFGA instance. It is the simplest setup, described in Setup OpenFGA with Docker 4 This is an NGINX service, which mimics an IDP system and exposes an JWKS endpoint with key material, heimdall is going to use to validate the JWT you’re going to use. Create a configuration file for heimdall, named heimdall-config.yaml with the following contents.\nmechanisms: authenticators: - id: jwt_auth (1) type: jwt config: jwks_endpoint: http://idp:8080/.well-known/jwks assertions: issuers: - demo_issuer authorizers: - id: openfga_check (2) type: remote config: endpoint: http://openfga:8080/stores/{{ .Values.store_id }}/check (3) payload: | (4) { \u0026#34;authorization_model_id\u0026#34;: \u0026#34;{{ .Values.model_id }}\u0026#34;, \u0026#34;tuple_key\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;, \u0026#34;relation\u0026#34;:\u0026#34;{{ .Values.relation }}\u0026#34;, \u0026#34;object\u0026#34;:\u0026#34;{{ .Values.object }}\u0026#34; } } expressions: - expression: | Payload.allowed == true (5) contextualizers: - id: openfga_list (6) type: generic config: endpoint: http://openfga:8080/stores/{{ .Values.store_id }}/list-objects (7) payload: | (8) { \u0026#34;authorization_model_id\u0026#34;: \u0026#34;{{ .Values.model_id }}\u0026#34;, \u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;, \u0026#34;relation\u0026#34;:\u0026#34;{{ .Values.relation }}\u0026#34;, \u0026#34;type\u0026#34;:\u0026#34;document\u0026#34; } finalizers: - id: create_jwt (9) type: jwt config: signer: key_store: path: /etc/heimdall/signer.pem providers: file_system: (10) src: /etc/heimdall/rules watch: true 1 This and the following lines define and configure the jwt authenticator named jwt_auth. With the given configuration it will check whether a request contains an Authorization header with a bearer token in JWT format and validate it using key material fetched from the JWKS endpoint. 2 Here we define and configure a remote authorizer named openfga_check, which we’re going to use for the actual authorization purposes in our rules. 3 Here we define the endpoint to be used for the authorization checks. Most probably, you’ll want to hard code your OpenFGA model id. Since, we’re going to create the model, when we start our setup, we’ll reference it in our rule via store_id. We use a very simple endpoint configuration here by just specifying the actual url. If required, you can specify API keys, and many more. Take a look at the linked documentation of this property. 4 This is the definition of our payload to be sent to the check endpoint. As we don’t know the model id as well, we’ll configure it in our rule. The user will be taken from the Subject create by heimdall, and the relation and object will be specified in our rule. 5 In case of a successful response, the response from the check endpoint will look like {\u0026#34;allowed\u0026#34;: true}. Otherwise, it will be {\u0026#34;allowed\u0026#34;: false}. With the expression here, we perform the required verification. 6 Here we define and configure a generic contextualizer named openfga_list. 7 As with the authorization mechanism, defined above, here we configure the endpoint to list the allowed objects. 8 The payload configuration used while communicating to the configured endpoint. 9 The following two lines define the jwt finalizer. With the given configuration, it will create a jwt out of the subject object with standard claims and set the sub claim to the value of subject’s ID. 10 The last few lines of the configure the file_system provider, which allows loading of regular rules from the file system. Create a file, named signer.pem with the following content. This is our key store with a private key, you’ve seen in the configuration above.\n-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy 1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI zlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X XVwR/5tokqFVrFxt/5c1x7VdccF4nNM= -----END EC PRIVATE KEY----- Do not use it for purposes beyond this tutorial! Configure NGINX to expose a static endpoint serving a JWKS document under the .well-known path, so heimdall is able to verify the JWT, we’re going to use. Create a file named idp.nginx with the following content:\nworker_processes 1; user nginx; pid /var/run/nginx.pid; events { worker_connections 1024; } http { keepalive_timeout 65; server { listen 8080; location /.well-known/jwks { default_type application/json; root /var/www/nginx; try_files /jwks.json =404; } } } In addition, create a file named jwks.json with the public key required to verify the tokens we’re going to use.\n{ \u0026#34;keys\u0026#34;: [ { \u0026#34;use\u0026#34;: \u0026#34;sig\u0026#34;, \u0026#34;kty\u0026#34;: \u0026#34;EC\u0026#34;, \u0026#34;kid\u0026#34;: \u0026#34;key-2\u0026#34;, \u0026#34;crv\u0026#34;: \u0026#34;P-256\u0026#34;, \u0026#34;alg\u0026#34;: \u0026#34;ES256\u0026#34;, \u0026#34;x\u0026#34;: \u0026#34;NnU0iWRq7szZP_8Ir3D4BShUEtcW1dHpuvlCgB6ecE0\u0026#34;, \u0026#34;y\u0026#34;: \u0026#34;X71tZm51ovUPFNKE0bsi5XF-FtIykEfk1O83EHNkSdo\u0026#34; } ] } Create Authorization Model \u0026amp; Rules The static configuration of our services is in place. Let us now create the actual authorization model and based on it the required heimdall rules.\nStart our setup with docker compose up and wait until all services are up and running.\nCreate the OpenFGA store as also described in Create Store with\ncurl -X POST http://127.0.0.1:8080/stores \\ -H \u0026#34;content-type: application/json\u0026#34; \\ -d \u0026#39;{\u0026#34;name\u0026#34;: \u0026#34;FGA Demo Store\u0026#34;}\u0026#39; This call should result in an output similar to\n{ \u0026#34;id\u0026#34;:\u0026#34;01HSXG2XSZJMQG99EVXB4QQX8P\u0026#34;, \u0026#34;name\u0026#34;:\u0026#34;FGA Demo Store\u0026#34;, \u0026#34;created_at\u0026#34;:\u0026#34;2024-03-26T13:44:37.439559338Z\u0026#34;, \u0026#34;updated_at\u0026#34;:\u0026#34;2024-03-26T13:44:37.439559338Z\u0026#34; } Note or write down the value of the store id returned.\nConfigure the authorization model as also described in Configure Model with\ncurl -X POST http://127.0.0.1:8080/stores/\u0026lt;the id from above\u0026gt;/authorization-models \\ -H \u0026#34;content-type: application/json\u0026#34; \\ -d \u0026#39;{\u0026#34;schema_version\u0026#34;:\u0026#34;1.1\u0026#34;,\u0026#34;type_definitions\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;},{\u0026#34;type\u0026#34;:\u0026#34;document\u0026#34;,\u0026#34;relations\u0026#34;:{\u0026#34;reader\u0026#34;:{\u0026#34;this\u0026#34;:{}},\u0026#34;writer\u0026#34;:{\u0026#34;this\u0026#34;:{}},\u0026#34;owner\u0026#34;:{\u0026#34;this\u0026#34;:{}}},\u0026#34;metadata\u0026#34;:{\u0026#34;relations\u0026#34;:{\u0026#34;reader\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]},\u0026#34;writer\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]},\u0026#34;owner\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]}}}}]}\u0026#39; This call should result in an output similar to\n{ \u0026#34;authorization_model_id\u0026#34;:\u0026#34;01HSXG7TBQEJ7GBPKQR2VYH24G\u0026#34; } Note or write down the value of authorization_model_id.\nLet us now create a rule set for heimdall. Create a file named demo.yaml with the following contents in the rules directory\nversion: \u0026#34;1alpha4\u0026#34; rules: - id: access_document (1) match: routes: - path: /document/:id (2) methods: [ GET, POST, DELETE ] forward_to: (3) host: upstream:8081 execute: - authenticator: jwt_auth (4) - authorizer: openfga_check (5) config: values: store_id: 01HSXG2XSZJMQG99EVXB4QQX8P (6) model_id: 01HSXG7TBQEJ7GBPKQR2VYH24G (7) relation: \u0026gt; (8) {{- if eq .Request.Method \u0026#34;GET\u0026#34; -}} reader {{- else if eq .Request.Method \u0026#34;POST\u0026#34; -}} creator {{- else if eq .Request.Method \u0026#34;DELETE\u0026#34; -}} deleter {{- else -}} unknown {{- end -}} object: \u0026gt; document:{{- .Request.URL.Captures.id -}} (9) - finalizer: create_jwt (10) - id: list_documents (11) match: routes: - path: /documents (12) methods: [ GET ] (14) forward_to: (13) host: upstream:8081 execute: (15) - authenticator: jwt_auth - contextualizer: openfga_list config: values: store_id: 01HSXG2XSZJMQG99EVXB4QQX8P model_id: 01HSXG7TBQEJ7GBPKQR2VYH24G relation: reader - finalizer: create_jwt config: claims: | {{ toJson .Outputs.openfga_list }} (16) 1 Our rule set consists of two rules. The first one has the id access_document 2 This rule should match urls of the following form /document/\u0026lt;id\u0026gt;, with id being the identifier of a document. 3 If the execution of the authentication \u0026amp; authorization pipeline was successful, the request should be forwarded to the upstream:8081 host. 4 The authentication \u0026amp; authorization pipeline starts with the reference to the previously defined authenticator jwt_auth 5 Next, we specify the openfga_check authorizer and also configure the rule specific settings 6 Replace the value here with the store id, you’ve received in step 6 7 Replace the value here with the authorization model id, you’ve received in step 7 8 Here, we set the relation depending on the used HTTP request method 9 Our object reference. We use the value captured by the wildcard named id. 10 Reference to the previously configured finalizer to create a JWT to be forwarded to our upstream service 11 This is our second rule. It has the id list_documents. 12 And matches any request of the form /documents 13 As the previous rule, this one forwards the request to the upstream:8081 host on successful completion of the authentication \u0026amp; authorization pipeline 14 Unlike the access_document rule, this one allows only HTTP GET methods for the matched urls. 15 The authentication \u0026amp; authorization pipeline is pretty similar to the previous rule. The main difference is the usage of the openfga_list contextualizer instead of the openfga_check authorizer and the reconfiguration of the create_jwt finalizer. As with the previous rule, replace the store_id and model_id with the values, you’ve received above. 16 Here, we reconfigure our finalizer to include the results from the openfga_list contextualizer into the created JWT. Update Relationship Tuples Having everything in place, time to configure the actual permissions. As with the previous steps, this one is based on Update Relationship Tuples from the official OpenFGA guide. So, let us give our user anne at least the read permission.\nIf you skip this step and directly continue with Use the Setup, you’ll always receive a 403 Forbidden response. Call the OpenFGA write endpoint as also described in Calling Write API To Add New Relationship Tuples to create a reader relationship between our user anne and the document with the id 1234. Replace the store id and the authorization model id with those, you’ve received while following the steps above:\ncurl -X POST http://127.0.0.1:8080/stores/\u0026lt;the store id from above\u0026gt;/write \\ -H \u0026#34;content-type: application/json\u0026#34; \\ -d \u0026#39;{ \u0026#34;authorization_model_id\u0026#34;: \u0026#34;\u0026lt;the authorization model id from above\u0026gt;\u0026#34;, \u0026#34;writes\u0026#34;: { \u0026#34;tuple_keys\u0026#34; : [ { \u0026#34;user\u0026#34;:\u0026#34;user:anne\u0026#34;, \u0026#34;relation\u0026#34;:\u0026#34;reader\u0026#34;, \u0026#34;object\u0026#34;:\u0026#34;document:1234\u0026#34; } ] } }\u0026#39; Verify anne has the required permissions\ncurl -X POST http://127.0.0.1:8080/stores/\u0026lt;the store id from above\u0026gt;/check \\ -H \u0026#34;content-type: application/json\u0026#34; \\ -d \u0026#39;{ \u0026#34;authorization_model_id\u0026#34;: \u0026#34;\u0026lt;the authorization model id from above\u0026gt;\u0026#34;, \u0026#34;tuple_key\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;user:anne\u0026#34;, \u0026#34;relation\u0026#34;: \u0026#34;reader\u0026#34;, \u0026#34;object\u0026#34;: \u0026#34;document:1234\u0026#34; } }\u0026#39; You should receive the following response:\n{\u0026#34;allowed\u0026#34;:true, \u0026#34;resolution\u0026#34;:\u0026#34;\u0026#34;} Use the Setup We have now definitely everything in place to allow our user anne to at least read the document with the id 1234 and also list the documents anne has access to.\nTry executing the following command:\n$ curl -X GET -H \u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0yIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjcyMzUxODUsImlhdCI6MTcxMTg3NTE4NSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI1ZDJjM2E3OC1hM2Y5LTRlNmYtOTExYi0xZjZmZWQ5ODE3YTciLCJuYmYiOjE3MTE4NzUxODUsInN1YiI6ImFubmUifQ.wH7HOs-w8YbsOLJcZ9bHBuY5lCBZmYUhQGLJyEbePJZ_WlyR7aa0QmCc3Yx9JsSs3HDmnIbD2wUaFTe2rZWtqA\u0026#34; \\ 127.0.0.1:9090/document/1234 You should see an output similar to the one shown below. Since our upstream does just echo everything back it receives, it represents a successful response to read the document with the id 1234.\nHostname: 94e60bba8498 IP: 127.0.0.1 IP: 172.19.0.2 RemoteAddr: 172.19.0.4:43688 GET /admin HTTP/1.1 Host: upstream:8081 User-Agent: curl/8.2.1 Accept: */* Accept-Encoding: gzip Authorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2OTQ5MzAsImlhdCI6MTcxODY5NDYzMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJiNzgyZGE4YS1mMDFlLTRmYmUtYTlkZC04MzdiYzYzYzlhODUiLCJuYmYiOjE3MTg2OTQ2MzAsInN1YiI6ImFubmUifQ.xANlIPmRWdMraL_j0i-0cK4NVhqopzgSc5_u0m4Hyg4VAFQ3ZHuuap1ZD9hs8ZkBQGin9-vPsBeVrQr40OfAev7WKyNVPpIpmFBAU8fX15kXgVXox29kgBAcAM2b2W-w Forwarded: for=172.19.0.1;host=127.0.0.1:9090;proto=http Let us list the documents our user has access to\n$ curl -H \u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0yIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjcyMzUxODUsImlhdCI6MTcxMTg3NTE4NSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI1ZDJjM2E3OC1hM2Y5LTRlNmYtOTExYi0xZjZmZWQ5ODE3YTciLCJuYmYiOjE3MTE4NzUxODUsInN1YiI6ImFubmUifQ.wH7HOs-w8YbsOLJcZ9bHBuY5lCBZmYUhQGLJyEbePJZ_WlyR7aa0QmCc3Yx9JsSs3HDmnIbD2wUaFTe2rZWtqA\u0026#34; \\ 127.0.0.1:9090/documents You should again see an output similar to the one shown below. However, if you take a closer look at the JWT from the Authorization header by e.g. making use of https://www.jstoolset.com/jwt, you’ll see it contains also a list of documents anne has access to.\nHostname: 94e60bba8498 IP: 127.0.0.1 IP: 172.19.0.2 RemoteAddr: 172.19.0.4:43688 GET /admin HTTP/1.1 Host: upstream:8081 User-Agent: curl/8.2.1 Accept: */* Accept-Encoding: gzip Authorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2OTUwODEsImlhdCI6MTcxODY5NDc4MSwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJiNWRhMDg2OC0yNTFhLTRhZmEtODk4ZS1hZThlYzdkZjMyZDEiLCJuYmYiOjE3MTg2OTQ3ODEsIm9iamVjdHMiOlsiZG9jdW1lbnQ6MTIzNCJdLCJzdWIiOiJhbm5lIn0.GY-4oi75KV8jQz5SgMzVMG_-CcCSi9XpmRE934Uq-A326MBwTcFuHysSYmWNz85wwG5zti2Jijn1T8Vm2fpTVEgEE6qltB9caVQlVNGDyF3uAVdpq9NRgHDcru3-15oB Forwarded: for=172.19.0.1;host=127.0.0.1:9090;proto=http Try accessing a document with the id 1235 or delete a document using the DELETE HTTP verb. Useless :). Heimdall won’t let you through. But you can add new relations as you did in Update Relationship Tuples to allow anne accessing further documents, or delete, or modify existing documents. Try that.\nCleanup Just stop the environment with CTRL-C and delete the created files. If you started docker compose in the background, tear the environment down with\n$ docker compose down ","description":"This guide explains how to integrate heimdall with the OpenFGA, a scalable open source authorization system.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://openfga.dev\"\u003eOpenFGA\u003c/a\u003e is inspired by \u003ca href=\"https://zanzibar.academy/\"\u003eGoogle’s Zanzibar\u003c/a\u003e, Google’s Relationship Based Access Control system and allows easily implementing authorization for any kind of application relying on Role-Based Access Control with additional Attribute-Based Access Control capabilities.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis guide is based on the OpenFGA’s official \u003ca href=\"https://openfga.dev/docs/getting-started\"\u003eGetting Started\u003c/a\u003e guide and highlights the relevant differences. It mimics a RESTful document management API, allowing listing, creating, reading, updating, and deleting documents. The API consists of two endpoints:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/document/\u0026lt;id\u0026gt;\u003c/code\u003e with \u003ccode\u003eid\u003c/code\u003e being the id of the document and the HTTP verbs reflecting the actual operations. E.g. a \u003ccode\u003eGET /document/1234\u003c/code\u003e request should read the document with the id \u003ccode\u003e1234\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/documents\u003c/code\u003e which supports the HTTP \u003ccode\u003eGET\u003c/code\u003e verb only and allows the user to list the documents it can access.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe identity of the user will be taken from a JWT.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nEven this guide addresses OpenFGA, it actually covers integration with any ReBAC system, be it Ory’s \u003ca href=\"https://www.ory.sh/keto/\"\u003eKeto\u003c/a\u003e, \u003ca href=\"https://authzed.com/spicedb\"\u003eSpiceDB\u003c/a\u003e from AuthZed, or any other system inspired by Google’s Zanzibar.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo be able to follow this guide, you’ll need the following tools installed locally:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/install/\"\u003eDocker\u003c/a\u003e,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/compose/install/\"\u003edocker-compose\u003c/a\u003e, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea text editor of your choice.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configure_the_base_setup\"\u003eConfigure the Base Setup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a directory in which we’re going to create further directories and files required for the setup and switch to it.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a directory named \u003ccode\u003erules\u003c/code\u003e. We’ll add the heimdall rule to it after our setup is started.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a \u003ccode\u003edocker-compose.yaml\u003c/code\u003e file with the following contents\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edadrus/heimdall:dev\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtainer_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e9090:4455\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./heimdall-config.yaml:/etc/heimdall/config.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./rules:/etc/heimdall/rules:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./signer.pem:/etc/heimdall/signer.pem:ro\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eserve proxy -c /etc/heimdall/config.yaml --insecure\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eupstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003econtainous/whoami:latest\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtainer_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e--port=8081\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eopenfga\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga/openfga:latest\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtainer_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erun\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e8080:8080\u0026#34;\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eidp\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enginx:1.25.4\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./idp.nginx:/etc/nginx/nginx.conf:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./jwks.json:/var/www/nginx/jwks.json:ro\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure heimdall to use a config file, we’re going to configure next and a rule directory, we’ll add our rules to.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWe’re using the \u003ccode\u003e--insecure\u003c/code\u003e flag here to simplify our setup, which disables enforcement of some security settings you can learn about more \u003ca href=\"/docs/operations/security/#_defaults\"\u003ehere\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we define the \u0026#34;upstream\u0026#34; service, which just echoes back everything it receives.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAnd these lines configure our OpenFGA instance. It is the simplest setup, described in \u003ca href=\"https://openfga.dev/docs/getting-started/setup-openfga/docker\"\u003eSetup OpenFGA with Docker\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is an NGINX service, which mimics an IDP system and exposes an JWKS endpoint with key material, heimdall is going to use to validate the JWT you’re going to use.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a configuration file for heimdall, named \u003ccode\u003eheimdall-config.yaml\u003c/code\u003e with the following contents.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_auth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ejwks_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://idp:8080/.well-known/jwks\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003edemo_issuer\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_check\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://openfga:8080/stores/{{ .Values.store_id }}/check\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;authorization_model_id\u0026#34;: \u0026#34;{{ .Values.model_id }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;tuple_key\u0026#34;: {\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;relation\u0026#34;:\u0026#34;{{ .Values.relation }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;object\u0026#34;:\u0026#34;{{ .Values.object }}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.allowed == true \u003c/span\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003econtextualizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_list\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://openfga:8080/stores/{{ .Values.store_id }}/list-objects\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;authorization_model_id\u0026#34;: \u0026#34;{{ .Values.model_id }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;relation\u0026#34;:\u0026#34;{{ .Values.relation }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;type\u0026#34;:\u0026#34;document\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e \u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e(9)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/signer.pem\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eproviders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e(10)\u003c/b\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/rules\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis and the following lines define and configure the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authenticators/#_jwt\"\u003ejwt\u003c/a\u003e\u003c/code\u003e authenticator named \u003ccode\u003ejwt_auth\u003c/code\u003e. With the given configuration it will check whether a request contains an \u003ccode\u003eAuthorization\u003c/code\u003e header with a bearer token in JWT format and validate it using key material fetched from the JWKS endpoint.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we define and configure a \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authorizers/#_remote\"\u003eremote\u003c/a\u003e\u003c/code\u003e authorizer named \u003ccode\u003eopenfga_check\u003c/code\u003e, which we’re going to use for the actual authorization purposes in our rules.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we define the endpoint to be used for the authorization checks. Most probably, you’ll want to hard code your OpenFGA model id. Since, we’re going to create the model, when we start our setup, we’ll reference it in our rule via \u003ccode\u003estore_id\u003c/code\u003e.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWe use a very simple \u003ccode\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eendpoint\u003c/a\u003e\u003c/code\u003e configuration here by just specifying the actual url. If required, you can specify API keys, and many more. Take a look at the linked documentation of this property.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is the definition of our payload to be sent to the check endpoint. As we don’t know the model id as well, we’ll configure it in our rule. The user will be taken from the \u003ccode\u003eSubject\u003c/code\u003e create by heimdall, and the relation and object will be specified in our rule.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eIn case of a successful response, the response from the check endpoint will look like \u003ccode\u003e{\u0026#34;allowed\u0026#34;: true}\u003c/code\u003e. Otherwise, it will be \u003ccode\u003e{\u0026#34;allowed\u0026#34;: false}\u003c/code\u003e. With the expression here, we perform the required verification.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we define and configure a \u003ccode\u003e\u003ca href=\"/docs/mechanisms/contextualizers/#_generic\"\u003egeneric\u003c/a\u003e\u003c/code\u003e contextualizer named \u003ccode\u003eopenfga_list\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAs with the authorization mechanism, defined above, here we configure the endpoint to list the allowed objects.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe payload configuration used while communicating to the configured endpoint.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e9\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe following two lines define the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/finalizers/#_jwt\"\u003ejwt\u003c/a\u003e\u003c/code\u003e finalizer. With the given configuration, it will create a jwt out of the subject object with standard claims and set the \u003ccode\u003esub\u003c/code\u003e claim to the value of subject’s ID.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e10\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe last few lines of the configure the \u003ccode\u003e\u003ca href=\"/docs/rules/providers/#_filesystem\"\u003efile_system\u003c/a\u003e\u003c/code\u003e provider, which allows loading of regular rules from the file system.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a file, named \u003ccode\u003esigner.pem\u003c/code\u003e with the following content. This is our key store with a private key, you’ve seen in the configuration above.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"s\"\u003e-----BEGIN EC PRIVATE KEY-----\u003c/span\u003e\n\u003cspan class=\"s\"\u003eMIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy\u003c/span\u003e\n\u003cspan class=\"s\"\u003e1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI\u003c/span\u003e\n\u003cspan class=\"s\"\u003ezlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X\u003c/span\u003e\n\u003cspan class=\"s\"\u003eXVwR/5tokqFVrFxt/5c1x7VdccF4nNM=\u003c/span\u003e\n\u003cspan class=\"s\"\u003e-----END EC PRIVATE KEY-----\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nDo not use it for purposes beyond this tutorial!\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eConfigure NGINX to expose a static endpoint serving a JWKS document under the \u003ccode\u003e.well-known\u003c/code\u003e path, so heimdall is able to verify the JWT, we’re going to use. Create a file named \u003ccode\u003eidp.nginx\u003c/code\u003e with the following content:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eworker_processes 1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\nuser nginx\u003cspan class=\"p\"\u003e;\u003c/span\u003e\npid /var/run/nginx.pid\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\nevents \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n worker_connections 1024\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\nhttp \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n keepalive_timeout 65\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n server \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n listen 8080\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n location /.well-known/jwks \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n default_type application/json\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n root /var/www/nginx\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n try_files /jwks.json \u003cspan class=\"o\"\u003e=\u003c/span\u003e404\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition, create a file named \u003ccode\u003ejwks.json\u003c/code\u003e with the public key required to verify the tokens we’re going to use.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;keys\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;use\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;sig\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;kty\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;EC\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;kid\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;key-2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;crv\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;P-256\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;alg\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;ES256\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;x\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;NnU0iWRq7szZP_8Ir3D4BShUEtcW1dHpuvlCgB6ecE0\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;y\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;X71tZm51ovUPFNKE0bsi5XF-FtIykEfk1O83EHNkSdo\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_create_authorization_model_rules\"\u003eCreate Authorization Model \u0026amp; Rules\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe static configuration of our services is in place. Let us now create the actual authorization model and based on it the required heimdall rules.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eStart our setup with \u003ccode\u003edocker compose up\u003c/code\u003e and wait until all services are up and running.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate the OpenFGA store as also described in \u003ca href=\"https://openfga.dev/docs/getting-started/create-store\"\u003eCreate Store\u003c/a\u003e with\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003ecurl \u003cspan class=\"nt\"\u003e-X\u003c/span\u003e POST http://127.0.0.1:8080/stores \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;content-type: application/json\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-d\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;{\u0026#34;name\u0026#34;: \u0026#34;FGA Demo Store\u0026#34;}\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis call should result in an output similar to\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;01HSXG2XSZJMQG99EVXB4QQX8P\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;FGA Demo Store\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;created_at\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;2024-03-26T13:44:37.439559338Z\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;updated_at\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;2024-03-26T13:44:37.439559338Z\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNote or write down the value of the store \u003ccode\u003eid\u003c/code\u003e returned.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eConfigure the authorization model as also described in \u003ca href=\"https://openfga.dev/docs/getting-started/configure-model\"\u003eConfigure Model\u003c/a\u003e with\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003ecurl \u003cspan class=\"nt\"\u003e-X\u003c/span\u003e POST http://127.0.0.1:8080/stores/\u0026lt;the \u003cspan class=\"nb\"\u003eid \u003c/span\u003efrom above\u0026gt;/authorization-models \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;content-type: application/json\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-d\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;{\u0026#34;schema_version\u0026#34;:\u0026#34;1.1\u0026#34;,\u0026#34;type_definitions\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;},{\u0026#34;type\u0026#34;:\u0026#34;document\u0026#34;,\u0026#34;relations\u0026#34;:{\u0026#34;reader\u0026#34;:{\u0026#34;this\u0026#34;:{}},\u0026#34;writer\u0026#34;:{\u0026#34;this\u0026#34;:{}},\u0026#34;owner\u0026#34;:{\u0026#34;this\u0026#34;:{}}},\u0026#34;metadata\u0026#34;:{\u0026#34;relations\u0026#34;:{\u0026#34;reader\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]},\u0026#34;writer\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]},\u0026#34;owner\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]}}}}]}\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis call should result in an output similar to\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;authorization_model_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;01HSXG7TBQEJ7GBPKQR2VYH24G\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNote or write down the value of \u003ccode\u003eauthorization_model_id\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eLet us now create a rule set for heimdall. Create a file named \u003ccode\u003edemo.yaml\u003c/code\u003e with the following contents in the \u003ccode\u003erules\u003c/code\u003e directory\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_document\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/document/:id\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"nv\"\u003eGET\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"nv\"\u003ePOST\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"nv\"\u003eDELETE\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_auth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_check\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003estore_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e01HSXG2XSZJMQG99EVXB4QQX8P\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003emodel_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e01HSXG7TBQEJ7GBPKQR2VYH24G\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"na\"\u003erelation\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e\u0026gt;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n \u003cspan class=\"s\"\u003e{{- if eq .Request.Method \u0026#34;GET\u0026#34; -}} reader\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{- else if eq .Request.Method \u0026#34;POST\u0026#34; -}} creator\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{- else if eq .Request.Method \u0026#34;DELETE\u0026#34; -}} deleter\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{- else -}} unknown\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{- end -}}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eobject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"s\"\u003edocument:{{- .Request.URL.Captures.id -}} \u003c/span\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e(9)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e \u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e(10)\u003c/b\u003e\n\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003elist_documents\u003c/span\u003e \u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e(11)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/documents\u003c/span\u003e \u003ci class=\"conum\" data-value=\"12\"\u003e\u003c/i\u003e\u003cb\u003e(12)\u003c/b\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"nv\"\u003eGET\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e \u003ci class=\"conum\" data-value=\"14\"\u003e\u003c/i\u003e\u003cb\u003e(14)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"13\"\u003e\u003c/i\u003e\u003cb\u003e(13)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"15\"\u003e\u003c/i\u003e\u003cb\u003e(15)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_auth\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_list\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003estore_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e01HSXG2XSZJMQG99EVXB4QQX8P\u003c/span\u003e\n \u003cspan class=\"na\"\u003emodel_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e01HSXG7TBQEJ7GBPKQR2VYH24G\u003c/span\u003e\n \u003cspan class=\"na\"\u003erelation\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ereader\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclaims\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ toJson .Outputs.openfga_list }} \u003c/span\u003e\u003ci class=\"conum\" data-value=\"16\"\u003e\u003c/i\u003e\u003cb\u003e(16)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eOur rule set consists of two rules. The first one has the id \u003ccode\u003eaccess_document\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis rule should match urls of the following form \u003ccode\u003e/document/\u0026lt;id\u0026gt;\u003c/code\u003e, with id being the identifier of a document.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eIf the execution of the authentication \u0026amp; authorization pipeline was successful, the request should be forwarded to the \u003ccode\u003eupstream:8081\u003c/code\u003e host.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe authentication \u0026amp; authorization pipeline starts with the reference to the previously defined authenticator \u003ccode\u003ejwt_auth\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eNext, we specify the \u003ccode\u003eopenfga_check\u003c/code\u003e authorizer and also configure the rule specific settings\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eReplace the value here with the store id, you’ve received in step 6\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eReplace the value here with the authorization model id, you’ve received in step 7\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we set the relation depending on the used HTTP request method\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e9\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eOur object reference. We use the value captured by the wildcard named \u003ccode\u003eid\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e10\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eReference to the previously configured finalizer to create a JWT to be forwarded to our upstream service\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e11\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is our second rule. It has the id \u003ccode\u003elist_documents\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"12\"\u003e\u003c/i\u003e\u003cb\u003e12\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAnd matches any request of the form \u003ccode\u003e/documents\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"13\"\u003e\u003c/i\u003e\u003cb\u003e13\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAs the previous rule, this one forwards the request to the \u003ccode\u003eupstream:8081\u003c/code\u003e host on successful completion of the authentication \u0026amp; authorization pipeline\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"14\"\u003e\u003c/i\u003e\u003cb\u003e14\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eUnlike the \u003ccode\u003eaccess_document\u003c/code\u003e rule, this one allows only HTTP GET methods for the matched urls.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"15\"\u003e\u003c/i\u003e\u003cb\u003e15\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe authentication \u0026amp; authorization pipeline is pretty similar to the previous rule. The main difference is the usage of the \u003ccode\u003eopenfga_list\u003c/code\u003e contextualizer instead of the \u003ccode\u003eopenfga_check\u003c/code\u003e authorizer and the reconfiguration of the \u003ccode\u003ecreate_jwt\u003c/code\u003e finalizer. As with the previous rule, replace the \u003ccode\u003estore_id\u003c/code\u003e and \u003ccode\u003emodel_id\u003c/code\u003e with the values, you’ve received above.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"16\"\u003e\u003c/i\u003e\u003cb\u003e16\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we reconfigure our finalizer to include the results from the \u003ccode\u003eopenfga_list\u003c/code\u003e contextualizer into the created JWT.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_update_relationship_tuples\"\u003eUpdate Relationship Tuples\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHaving everything in place, time to configure the actual permissions. As with the previous steps, this one is based on \u003ca href=\"https://openfga.dev/docs/getting-started/update-tuples\"\u003eUpdate Relationship Tuples\u003c/a\u003e from the official OpenFGA guide. So, let us give our user \u003ccode\u003eanne\u003c/code\u003e at least the \u003ccode\u003eread\u003c/code\u003e permission.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you skip this step and directly continue with \u003ca href=\"#_use_the_setup\"\u003eUse the Setup\u003c/a\u003e, you’ll always receive a \u003ccode\u003e403 Forbidden\u003c/code\u003e response.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eCall the OpenFGA write endpoint as also described in \u003ca href=\"https://openfga.dev/docs/getting-started/update-tuples#02-calling-write-api-to-add-new-relationship-tuples\"\u003eCalling Write API To Add New Relationship Tuples\u003c/a\u003e to create a reader relationship between our user \u003ccode\u003eanne\u003c/code\u003e and the document with the id \u003ccode\u003e1234\u003c/code\u003e. Replace the store id and the authorization model id with those, you’ve received while following the steps above:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003ecurl \u003cspan class=\"nt\"\u003e-X\u003c/span\u003e POST http://127.0.0.1:8080/stores/\u0026lt;the store \u003cspan class=\"nb\"\u003eid \u003c/span\u003efrom above\u0026gt;/write \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;content-type: application/json\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-d\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;{\n \u0026#34;authorization_model_id\u0026#34;: \u0026#34;\u0026lt;the authorization model id from above\u0026gt;\u0026#34;,\n \u0026#34;writes\u0026#34;: {\n \u0026#34;tuple_keys\u0026#34; : [\n {\n \u0026#34;user\u0026#34;:\u0026#34;user:anne\u0026#34;,\n \u0026#34;relation\u0026#34;:\u0026#34;reader\u0026#34;,\n \u0026#34;object\u0026#34;:\u0026#34;document:1234\u0026#34;\n }\n ]\n }\n }\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eVerify \u003ccode\u003eanne\u003c/code\u003e has the required permissions\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003ecurl \u003cspan class=\"nt\"\u003e-X\u003c/span\u003e POST http://127.0.0.1:8080/stores/\u0026lt;the store \u003cspan class=\"nb\"\u003eid \u003c/span\u003efrom above\u0026gt;/check \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;content-type: application/json\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-d\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;{\n \u0026#34;authorization_model_id\u0026#34;: \u0026#34;\u0026lt;the authorization model id from above\u0026gt;\u0026#34;,\n \u0026#34;tuple_key\u0026#34;: {\n \u0026#34;user\u0026#34;: \u0026#34;user:anne\u0026#34;,\n \u0026#34;relation\u0026#34;: \u0026#34;reader\u0026#34;,\n \u0026#34;object\u0026#34;: \u0026#34;document:1234\u0026#34;\n }\n }\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou should receive the following response:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;allowed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;resolution\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_use_the_setup\"\u003eUse the Setup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWe have now definitely everything in place to allow our user \u003ccode\u003eanne\u003c/code\u003e to at least read the document with the id \u003ccode\u003e1234\u003c/code\u003e and also list the documents \u003ccode\u003eanne\u003c/code\u003e has access to.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eTry executing the following command:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl \u003cspan class=\"nt\"\u003e-X\u003c/span\u003e GET \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0yIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjcyMzUxODUsImlhdCI6MTcxMTg3NTE4NSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI1ZDJjM2E3OC1hM2Y5LTRlNmYtOTExYi0xZjZmZWQ5ODE3YTciLCJuYmYiOjE3MTE4NzUxODUsInN1YiI6ImFubmUifQ.wH7HOs-w8YbsOLJcZ9bHBuY5lCBZmYUhQGLJyEbePJZ_WlyR7aa0QmCc3Yx9JsSs3HDmnIbD2wUaFTe2rZWtqA\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n 127.0.0.1:9090/document/1234\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou should see an output similar to the one shown below. Since our upstream does just echo everything back it receives, it represents a successful response to read the document with the id \u003ccode\u003e1234\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eHostname: 94e60bba8498\nIP: 127.0.0.1\nIP: 172.19.0.2\nRemoteAddr: 172.19.0.4:43688\nGET /admin HTTP/1.1\nHost: upstream:8081\nUser-Agent: curl/8.2.1\nAccept: \u003cspan class=\"k\"\u003e*\u003c/span\u003e/\u003cspan class=\"k\"\u003e*\u003c/span\u003e\nAccept-Encoding: \u003cspan class=\"nb\"\u003egzip\n\u003c/span\u003eAuthorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2OTQ5MzAsImlhdCI6MTcxODY5NDYzMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJiNzgyZGE4YS1mMDFlLTRmYmUtYTlkZC04MzdiYzYzYzlhODUiLCJuYmYiOjE3MTg2OTQ2MzAsInN1YiI6ImFubmUifQ.xANlIPmRWdMraL_j0i-0cK4NVhqopzgSc5_u0m4Hyg4VAFQ3ZHuuap1ZD9hs8ZkBQGin9-vPsBeVrQr40OfAev7WKyNVPpIpmFBAU8fX15kXgVXox29kgBAcAM2b2W-w\nForwarded: \u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e172.19.0.1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003ehost\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e127.0.0.1:9090\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003eproto\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttp\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eLet us list the documents our user has access to\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0yIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjcyMzUxODUsImlhdCI6MTcxMTg3NTE4NSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI1ZDJjM2E3OC1hM2Y5LTRlNmYtOTExYi0xZjZmZWQ5ODE3YTciLCJuYmYiOjE3MTE4NzUxODUsInN1YiI6ImFubmUifQ.wH7HOs-w8YbsOLJcZ9bHBuY5lCBZmYUhQGLJyEbePJZ_WlyR7aa0QmCc3Yx9JsSs3HDmnIbD2wUaFTe2rZWtqA\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n 127.0.0.1:9090/documents\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou should again see an output similar to the one shown below. However, if you take a closer look at the JWT from the \u003ccode\u003eAuthorization\u003c/code\u003e header by e.g. making use of \u003ca href=\"https://www.jstoolset.com/jwt\" class=\"bare\"\u003ehttps://www.jstoolset.com/jwt\u003c/a\u003e, you’ll see it contains also a list of documents \u003ccode\u003eanne\u003c/code\u003e has access to.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eHostname: 94e60bba8498\nIP: 127.0.0.1\nIP: 172.19.0.2\nRemoteAddr: 172.19.0.4:43688\nGET /admin HTTP/1.1\nHost: upstream:8081\nUser-Agent: curl/8.2.1\nAccept: \u003cspan class=\"k\"\u003e*\u003c/span\u003e/\u003cspan class=\"k\"\u003e*\u003c/span\u003e\nAccept-Encoding: \u003cspan class=\"nb\"\u003egzip\n\u003c/span\u003eAuthorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2OTUwODEsImlhdCI6MTcxODY5NDc4MSwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJiNWRhMDg2OC0yNTFhLTRhZmEtODk4ZS1hZThlYzdkZjMyZDEiLCJuYmYiOjE3MTg2OTQ3ODEsIm9iamVjdHMiOlsiZG9jdW1lbnQ6MTIzNCJdLCJzdWIiOiJhbm5lIn0.GY-4oi75KV8jQz5SgMzVMG_-CcCSi9XpmRE934Uq-A326MBwTcFuHysSYmWNz85wwG5zti2Jijn1T8Vm2fpTVEgEE6qltB9caVQlVNGDyF3uAVdpq9NRgHDcru3-15oB\nForwarded: \u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e172.19.0.1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003ehost\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e127.0.0.1:9090\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003eproto\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttp\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eTry accessing a document with the id \u003ccode\u003e1235\u003c/code\u003e or delete a document using the \u003ccode\u003eDELETE\u003c/code\u003e HTTP verb. Useless :). Heimdall won’t let you through. But you can add new relations as you did in \u003ca href=\"#_update_relationship_tuples\"\u003eUpdate Relationship Tuples\u003c/a\u003e to allow \u003ccode\u003eanne\u003c/code\u003e accessing further documents, or delete, or modify existing documents. Try that.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cleanup\"\u003eCleanup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eJust stop the environment with \u003ccode\u003eCTRL-C\u003c/code\u003e and delete the created files. If you started docker compose in the background, tear the environment down with\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003edocker compose down\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","Authorization Services"],"tags":null,"title":"Integration with OpenFGA","url":"/guides/authz/openfga/"},{"categories":null,"content":" By the end of this guide, you’ll have a functional setup where heimdall uses Keycloak to authenticate users and route requests based on their authentication status and roles for role-based access control.\nAlthough this guide uses Keycloak as identity provider (IDP), you can achieve the same results with Zitadel, Boruta, or any other OpenID Connect-compatible IDP.\nOverview In this guide, we’ll set up a Docker Compose environment where heimdall secures services and controls access to specific endpoints:\n/ - This endpoint is open to everyone.\n/user - Accessible only to authenticated users.\n/admin - Accessible only to users with the admin role.\nThere are also some further endpoints, which you’ll learn about during the setup.\nTechnically, the setup includes:\ncontainous/whoami - A service that echoes back everything it receives, simulating our main service with endpoints mentioned above.\nKeycloak - Our identity provider.\nOAuth2-Proxy - Handles the Authorization Code Grant flow for the actual user login.\nheimdall - Manages everything to enforce the requirements outlined above.\nPrerequisites To be able to follow this guide you need the following tools installed locally:\nDocker,\ndocker-compose, and\na text editor of your choice.\nConfigure the Base Setup Create a directory for the configuration files we’ll be using (referred to as the root directory in this guide). Inside this root directory, create two additional directories named rules and initdb. The former will be used for heimdall rules and the latter for DB initialization scripts.\nCreate a config file for heimdall named heimdall-config.yaml with the following contents in the root directory:\nlog: (1) level: debug tracing: enabled: false metrics: enabled: false mechanisms: (2) authenticators: - id: deny_all (3) type: unauthorized - id: anon (4) type: anonymous - id: auth (5) type: generic config: identity_info_endpoint: http://oauth2-proxy:4180/oauth2/userinfo authentication_data_source: - cookie: SESSION forward_cookies: - SESSION subject: id: \u0026#34;user\u0026#34; authorizers: - id: cel (6) type: cel config: expressions: - expression: \u0026#34;true == false\u0026#34; finalizers: - id: create_jwt (7) type: jwt config: signer: key_store: path: /etc/heimdall/signer.pem claims: | {{- dict \u0026#34;attrs\u0026#34; .Subject.Attributes | toJson -}} - id: noop (8) type: noop error_handlers: (9) - id: redirect_to_idp type: redirect config: to: http://127.0.0.1:9090/oauth2/start?rd={{ .Request.URL | urlenc }} - id: redirect_to_error_page type: redirect config: to: https://www.google.com/search?q=access+denied\u0026amp;udm=2 default_rule: (10) execute: - authenticator: deny_all - finalizer: create_jwt on_error: - error_handler: redirect_to_error_page if: | type(Error) in [authorization_error, authentication_error] \u0026amp;\u0026amp; Request.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;) providers: (11) file_system: src: /etc/heimdall/rules watch: true 1 By default, heimdall emits logs on error level, but to better understand its operations, we’re setting the log level to debug. This way, you’ll see not only the results of rule executions (which is what you would see if we set the log level to info), but also detailed information about what’s happening within each rule. We’re also disabling tracing and metrics collection to avoid errors related to the missing OTEL agent, which is used by default. For more details on logging and other observability options, see the Observability chapter. 2 We define our catalogue of mechanisms for use in our default rule and upstream service-specific rules. 3 These lines define the unauthorized authenticator, named deny_all, which rejects all requests. 4 These lines define the anonymous authenticator, named anon, which allows all requests and creates a subject with the ID set to anonymous. More information about subjects and other objects can be found here. 5 These and the following lines set up the generic authenticator, named auth. This configuration checks if a request includes a Cookie named SESSION, and then sends it to the http://oauth2-proxy:4180/oauth2/userinfo endpoint to get user information. If successful, heimdall extracts the user identifier from the user property in the response. If there’s an error (e.g. the SESSION cookie is not present or the response from the OAuth2-Proxy contains an error), an authentication error is triggered. 6 These lines define a cel authorizer that is configured to always fail. We’ll improve this in our upstream-specific rule. 7 These lines define the jwt finalizer. It creates a JWT from the subject object with standard claims, setting the sub claim to the subject’s ID. The key for signing the JWT comes from a key store we’ll configure later. 8 These two lines define the noop finalizer, which we’ll use for public endpoints. 9 Here, we set up two redirect error handlers: one redirects to the /oauth2/start endpoint with a deep link to the current URL, and the other redirects to Google with the search query \u0026#34;access denied\u0026#34;. 10 With all mechanisms defined, we configure our first rule - the default rule. This rule applies if no other rules match the request and serves as a base for defining regular (upstream service-specific) rules as well. It sets up a default authentication \u0026amp; authorization pipeline that rejects all requests using the deny_all authenticator. This rejection triggers the redirect_to_error_page error handler. If a regular rule overrides this authenticator, a JWT is created using the jwt finalizer. 11 The last few lines configure the file_system provider, which loads regular rules from the file system and watches for changes. This allows you to modify the rules while testing. Create a file named signer.pem and add the following content to it. This file should also be placed in the root directory and will act as our key store, containing the private key referenced in the configuration above.\n-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy 1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI zlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X XVwR/5tokqFVrFxt/5c1x7VdccF4nNM= -----END EC PRIVATE KEY----- Do not use it for purposes beyond this tutorial! Next, we’ll create rules for our main service - the one exposing /, /user and the /admin endpoints. To do this, create a file named upstream-rules.yaml in the rules directory with the following content:\nversion: \u0026#34;1alpha4\u0026#34; rules: - id: upstream:public (1) match: routes: - path: / - path: /favicon.ico forward_to: host: upstream:8081 execute: - authenticator: anon - finalizer: noop - id: upstream:protected (2) match: routes: - path: /user - path: /admin forward_to: host: upstream:8081 execute: - authenticator: auth - authorizer: cel if: Request.URL.Path == \u0026#39;/admin\u0026#39; config: expressions: - expression: | has(Subject.Attributes.groups) \u0026amp;\u0026amp; \u0026#34;role:admin\u0026#34; in Subject.Attributes.groups message: User is not admin on_error: - error_handler: redirect_to_idp if: | type(Error) == authentication_error \u0026amp;\u0026amp; Request.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;) - error_handler: redirect_to_error_page if: | type(Error) == authorization_error \u0026amp;\u0026amp; Request.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;) 1 This first rule is for the / endpoint. It instructs heimdall to pass requests to this endpoint directly through to our upstream service. 2 The second rule ensures that the /user endpoint is only accessible to authenticated users, while the /admin endpoint is only accessible to users with the admin role configured in our IDP. Next, we’ll create a rule for the OAuth2-Proxy, placed behind heimdall and publicly exposing only certain endpoints. Create a new file named oauth2-proxy-rules.yaml in the rules directory with the following content:\nversion: \u0026#34;1alpha4\u0026#34; rules: - id: oauth2-proxy:public match: routes: - path: /oauth2/start - path: /oauth2/callback forward_to: host: oauth2-proxy:4180 execute: - authenticator: anon - finalizer: noop Next, we’ll create a database initialization script to set up a database for Keycloak. In the initdb directory, create a file named initdb.sh with the following content, and make it executable by running chmod +x initdb.sh:\n#!/bin/bash set -e psql -v ON_ERROR_STOP=1 --username \u0026#34;$POSTGRES_USER\u0026#34; \u0026lt;\u0026lt;-EOSQL CREATE USER keycloak WITH PASSWORD \u0026#39;keycloak\u0026#39;; CREATE DATABASE keycloak OWNER keycloak; EOSQL Now, let’s bring everything together using a Docker Compose file. Create a file named docker-compose.yaml in the root directory with the following content:\nservices: heimdall: (1) image: dadrus/heimdall:dev ports: - \u0026#34;9090:4455\u0026#34; command: serve proxy --c /etc/heimdall/config.yaml --insecure volumes: - ./heimdall-config.yaml:/etc/heimdall/config.yaml:ro - ./rules:/etc/heimdall/rules:ro - ./signer.pem:/etc/heimdall/signer.pem:ro upstream: (2) image: containous/whoami:latest command: --port=8081 oauth2-proxy: (3) depends_on: - keycloak image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0-amd64 command: - --http-address - 0.0.0.0:4180 environment: OAUTH2_PROXY_CLIENT_ID: placeholder (4) OAUTH2_PROXY_CLIENT_SECRET: placeholder OAUTH2_PROXY_REDIRECT_URL: http://127.0.0.1:9090/oauth2/callback (5) OAUTH2_PROXY_PROVIDER: keycloak-oidc OAUTH2_PROXY_SKIP_PROVIDER_BUTTON: true OAUTH2_PROXY_COOKIE_SECRET: VerySecure!!!!!! OAUTH2_PROXY_COOKIE_NAME: SESSION OAUTH2_PROXY_WHITELIST_DOMAINS: 127.0.0.1:9090 OAUTH2_PROXY_OIDC_ISSUER_URL: http://keycloak:8080/realms/test (6) OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL: true (7) OAUTH2_PROXY_EMAIL_DOMAINS: \u0026#39;*\u0026#39; OAUTH2_PROXY_OIDC_EXTRA_AUDIENCES: account (8) OAUTH2_PROXY_LOGIN_URL: http://127.0.0.1:8080/realms/test/protocol/openid-connect/auth (9) OAUTH2_PROXY_OIDC_JWKS_URL: http://keycloak:8080/realms/test/protocol/openid-connect/certs OAUTH2_PROXY_REDEEM_URL: http://keycloak:8080/realms/test/protocol/openid-connect/token OAUTH2_PROXY_INSECURE_OIDC_SKIP_ISSUER_VERIFICATION: true OAUTH2_PROXY_SKIP_OIDC_DISCOVERY: true keycloak: (10) image: quay.io/keycloak/keycloak:25.0.4 command: [ \u0026#34;start-dev\u0026#34;, \u0026#34;--http-port\u0026#34;, \u0026#34;8080\u0026#34; ] ports: - \u0026#34;8080:8080\u0026#34; environment: KC_HOSTNAME: 127.0.0.1 KC_HOSTNAME_PORT: 8080 KC_HOSTNAME_STRICT_BACKCHANNEL: \u0026#34;true\u0026#34; KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin KC_HEALTH_ENABLED: \u0026#34;true\u0026#34; KC_LOG_LEVEL: info KC_DB_URL_HOST: postgresql KC_DB: postgres KC_DB_USERNAME: keycloak KC_DB_PASSWORD: keycloak depends_on: - postgresql postgresql: (11) image: postgres:13.11 volumes: - type: volume source: postgres-db target: /var/lib/postgresql/data read_only: false - ./initdb:/docker-entrypoint-initdb.d environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres volumes: postgres-db: 1 Here, we configure heimdall to use the previously defined configuration. We’re using the --insecure flag here to simplify our setup, which disables enforcement of some security settings you can learn about more here. 2 This section sets up the main service that we’ll be protecting. 3 This section defines the OAuth2-Proxy configuration, which heimdall will use to handle the Authorization Code Grant flow and manage the authentication session with a SESSION cookie. 4 The client ID and client secret values are placeholders. We will configure these in Keycloak. 5 Since the redirect URI, exposed as /oauth2/callback, is behind heimdall, we use the publicly accessible endpoint here. 6 The URL of the issuer that OAuth2-Proxy will use. We’ll create a corresponding realm in Keycloak to match this configuration. 7 The following two lines are required as we don’t want keycloak to verify the email addresses of the users we’ll be creating, and we want to allow any email domain. 8 To avoid creating a mapper to let Keycloak set a proper aud claim value, we allow the usage of account audience set by Keycloak by default. 9 These lines are only required as Keycloak is part of our docker compose setup, and we have to use different domain names while communicating with it. 10 This section sets up Keycloak. 11 Finally, this section configures our database. Create a Realm and a Client in Keycloak With the above configuration in place, follow these steps to start Keycloak and the database, initialize both, and create the OAuth2-Proxy client:\nIn the root directory, run docker compose up postgresql keycloak. Wait until the database is initialized and Keycloak has started.\nOpen your browser and go to http://127.0.0.1:8080. Log in using the admin credentials (both the username and password are set to admin in our setup).\nCreate a Realm named test. For detailed instructions, refer to the Keycloak documentation on creating a realm.\nWithin the test realm, create an OpenID Client. Follow the Keycloak documentation on creating an OIDC client. Enable \u0026#34;Client authentication\u0026#34; and \u0026#34;Standard Flow\u0026#34;, set http://127.0.0.1:9090/oauth2/callback as the \u0026#34;Valid Redirect URI\u0026#34; and http://127.0.0.1:9090/ as the \u0026#34;Home URL\u0026#34; and \u0026#34;Valid post logout redirect URIs\u0026#34; and note the \u0026#34;Client ID\u0026#34; and \u0026#34;Client Secret\u0026#34; (later can be found under the \u0026#34;Credentials\u0026#34; tab after completing the client creation wizard); we will use these to complete the OAuth2-Proxy configuration in our Docker Compose file.\nStop the docker compose setup with CTRL-C.\nUpdate OAuth2-Proxy Configuration We can now finalize the configuration and use the proper client id and secret for OAuth2-Proxy\nUpdate the OAUTH2_PROXY_CLIENT_ID and OAUTH2_PROXY_CLIENT_SECRET in the configuration of the OAuth2-Proxy in the docker compose file with the \u0026#34;Client ID\u0026#34; and \u0026#34;Client Secret\u0026#34; values from Keycloak\nUse the Setup We now have almost everything set up. The final step is to create a few users, including at least one with the admin role assigned.\nIn the root directory, run docker compose up. Wait until all services are up and running.\nOpen your browser and navigate to http://127.0.0.1:8080. Log in using the admin credentials (both username and password are set to admin).\nSelect the test realm and create an admin group with a role named admin assigned to it. For guidance, refer to the Keycloak documentation on creating Groups and Roles.\nCreate several users following the Keycloak documentation on managing users, and assign some of them to the admin group. Disable email verification during user creation to avoid sending verification emails to potentially non-existent addresses.\nNow, let’s test the setup:\nNavigate to http://127.0.0.1:9090/. You should see some text similar to the one shown below. This text is the response from our upstream service, which echoes back everything the browser sends in its request.\nHostname: 39f1815dd8ac IP: 127.0.0.1 IP: ::1 IP: 172.31.0.3 RemoteAddr: 172.31.0.2:37908 GET / HTTP/1.1 Host: upstream:8081 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8 Accept-Encoding: gzip, deflate, br, zstd Accept-Language: de,en-US;q=0.7,en;q=0.3 Dnt: 1 Forwarded: for=172.31.0.1;host=127.0.0.1:9090;proto=http Priority: u=0, i Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: none Sec-Fetch-User: ?1 Upgrade-Insecure-Requests: 1 X-Trp-Catalog: de Attempt to access the http://127.0.0.1:9090/user endpoint. You should be redirected to the Keycloak login page. Log in with any of the users you configured. After logging in, you should be redirected back to http://127.0.0.1:9090/user, where you’ll see some text similar to the one shown below. This indicates that the request hit the /user endpoint of our upstream service. You should also see a JWT token in the Authorization header, which is the result of the JWT finalizer we configured.\nHostname: 39f1815dd8ac IP: 127.0.0.1 IP: ::1 IP: 172.31.0.3 RemoteAddr: 172.31.0.2:37908 GET /user HTTP/1.1 Host: upstream:8081 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8 Accept-Encoding: gzip, deflate, br, zstd Accept-Language: de,en-US;q=0.7,en;q=0.3 Authorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJhdHRycyI6eyJlbWFpbCI6InRlc3QxQGV4YW1wbGUuY29tIiwiZ3JvdXBzIjpbInJvbGU6ZGVmYXVsdC1yb2xlcy10ZXN0Iiwicm9sZTpvZmZsaW5lX2FjY2VzcyIsInJvbGU6YWRtaW4iLCJyb2xlOnVtYV9hdXRob3JpemF0aW9uIiwicm9sZTphY2NvdW50Om1hbmFnZS1hY2NvdW50Iiwicm9sZTphY2NvdW50Om1hbmFnZS1hY2NvdW50LWxpbmtzIiwicm9sZTphY2NvdW50OnZpZXctcHJvZmlsZSJdLCJwcmVmZXJyZWRVc2VybmFtZSI6InRlc3QxIiwidXNlciI6IjQ5ZWE3Mjk3LWI0NzgtNDcxNC05NjM2LWQ5ZTk3ZmVkZmNhOSJ9LCJleHAiOjE3MjY0NjkyMTAsImlhdCI6MTcyNjQ2ODkxMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJkODg3Y2Q3MC1iYzhlLTQ2MTItODYzNS1lYTYwYjU1ZmU3MzciLCJuYmYiOjE3MjY0Njg5MTAsInN1YiI6IjQ5ZWE3Mjk3LWI0NzgtNDcxNC05NjM2LWQ5ZTk3ZmVkZmNhOSJ9.JLS__gH0wEHwB07DV9Rcrm9mo1xfXpqHoC8pbZ523KHV7QO3n2jrauiB4fVggB5DPe4tTUrp8X1e4nePXPniJyACyC7gmoBX5PJTbUPlalsw0WKOfYOcYXjwJDakId5r Cookie: SESSION=S77dk6NGQyyreWQ1enWRSCSP...wBsNTlidPgTBahs= Dnt: 1 Forwarded: for=172.31.0.1;host=127.0.0.1:9090;proto=http Priority: u=0, i Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: none Sec-Fetch-User: ?1 Upgrade-Insecure-Requests: 1 X-Trp-Catalog: de Try accessing the http://127.0.0.1:9090/admin endpoint with both a user not in the admin group and a user from the admin group. The user not in the admin group should see the \u0026#34;access denied\u0026#34; page, while the user from the admin group should be able to access the endpoint and see the echoed response from our upstream service.\nTo \u0026#34;logout\u0026#34; the user, just delete the cookies for http://127.0.0.1:9090 using the Web-Developer Tools of your browser. Attempts to access any not exposed endpoints, like http://127.0.0.1:9090/foo will always result in the \u0026#34;access denied\u0026#34; page.\nCleanup Just stop the environment with CTRL-C and delete the created files. If you started docker compose in the background, tear the environment down with docker-compose down.\n","description":"This guide will walk you through the process of integrating heimdall with an OpenID Connect provider to implement first-party authentication.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy the end of this guide, you’ll have a functional setup where heimdall uses \u003ca href=\"https://www.keycloak.org/\"\u003eKeycloak\u003c/a\u003e to authenticate users and route requests based on their authentication status and roles for role-based access control.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAlthough this guide uses Keycloak as identity provider (IDP), you can achieve the same results with \u003ca href=\"https://zitadel.com\"\u003eZitadel\u003c/a\u003e, \u003ca href=\"https://github.com/malach-it/boruta-server\"\u003eBoruta\u003c/a\u003e, or any other OpenID Connect-compatible IDP.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_overview\"\u003eOverview\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this guide, we’ll set up a Docker Compose environment where heimdall secures services and controls access to specific endpoints:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/\u003c/code\u003e - This endpoint is open to everyone.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/user\u003c/code\u003e - Accessible only to authenticated users.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/admin\u003c/code\u003e - Accessible only to users with the \u003ccode\u003eadmin\u003c/code\u003e role.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere are also some further endpoints, which you’ll learn about during the setup.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTechnically, the setup includes:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://hub.docker.com/r/containous/whoami/\"\u003econtainous/whoami\u003c/a\u003e - A service that echoes back everything it receives, simulating our main service with endpoints mentioned above.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://www.keycloak.org/\"\u003eKeycloak\u003c/a\u003e - Our identity provider.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://oauth2-proxy.github.io/oauth2-proxy/\"\u003eOAuth2-Proxy\u003c/a\u003e - Handles the Authorization Code Grant flow for the actual user login.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eheimdall - Manages everything to enforce the requirements outlined above.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo be able to follow this guide you need the following tools installed locally:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/install/\"\u003eDocker\u003c/a\u003e,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/compose/install/\"\u003edocker-compose\u003c/a\u003e, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea text editor of your choice.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configure_the_base_setup\"\u003eConfigure the Base Setup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a directory for the configuration files we’ll be using (referred to as the root directory in this guide). Inside this root directory, create two additional directories named \u003ccode\u003erules\u003c/code\u003e and \u003ccode\u003einitdb\u003c/code\u003e. The former will be used for heimdall rules and the latter for DB initialization scripts.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a config file for heimdall named \u003ccode\u003eheimdall-config.yaml\u003c/code\u003e with the following contents in the root directory:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edebug\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emetrics\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eunauthorized\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidentity_info_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://oauth2-proxy:4180/oauth2/userinfo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_data_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ecookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSESSION\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_cookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eSESSION\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003euser\u0026#34;\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etrue\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e==\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003efalse\u0026#34;\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/signer.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclaims\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{- dict \u0026#34;attrs\u0026#34; .Subject.Attributes | toJson -}}\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eerror_handlers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e(9)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect_to_idp\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://127.0.0.1:9090/oauth2/start?rd={{ .Request.URL | urlenc }}\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect_to_error_page\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://www.google.com/search?q=access+denied\u0026amp;udm=2\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003edefault_rule\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e(10)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003eon_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect_to_error_page\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) in [authorization_error, authentication_error] \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eRequest.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;)\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eproviders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e(11)\u003c/b\u003e\n \u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/rules\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eBy default, heimdall emits logs on \u003ccode\u003eerror\u003c/code\u003e level, but to better understand its operations, we’re setting the log level to \u003ccode\u003edebug\u003c/code\u003e. This way, you’ll see not only the results of rule executions (which is what you would see if we set the log level to \u003ccode\u003einfo\u003c/code\u003e), but also detailed information about what’s happening within each rule. We’re also disabling tracing and metrics collection to avoid errors related to the missing OTEL agent, which is used by default. For more details on logging and other observability options, see the \u003ca href=\"/docs/operations/observability/#_logging\"\u003eObservability\u003c/a\u003e chapter.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWe define our \u003ca href=\"/docs/mechanisms/catalogue/\"\u003ecatalogue of mechanisms\u003c/a\u003e for use in our \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e and \u003ca href=\"/docs/rules/regular_rule/\"\u003eupstream service-specific rules\u003c/a\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines define the \u003ccode\u003eunauthorized\u003c/code\u003e authenticator, named \u003ccode\u003edeny_all\u003c/code\u003e, which rejects all requests.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines define the \u003ccode\u003eanonymous\u003c/code\u003e authenticator, named \u003ccode\u003eanon\u003c/code\u003e, which allows all requests and creates a subject with the ID set to \u003ccode\u003eanonymous\u003c/code\u003e. More information about subjects and other objects can be found \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003ehere\u003c/a\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese and the following lines set up the \u003ccode\u003egeneric\u003c/code\u003e authenticator, named \u003ccode\u003eauth\u003c/code\u003e. This configuration checks if a request includes a \u003ccode\u003eCookie\u003c/code\u003e named \u003ccode\u003eSESSION\u003c/code\u003e, and then sends it to the \u003ccode\u003ehttp://oauth2-proxy:4180/oauth2/userinfo\u003c/code\u003e endpoint to get user information. If successful, heimdall extracts the user identifier from the \u003ccode\u003euser\u003c/code\u003e property in the response. If there’s an error (e.g. the \u003ccode\u003eSESSION\u003c/code\u003e cookie is not present or the response from the OAuth2-Proxy contains an error), an authentication error is triggered.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines define a \u003ccode\u003ecel\u003c/code\u003e authorizer that is configured to always fail. We’ll improve this in our upstream-specific rule.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines define the \u003ccode\u003ejwt\u003c/code\u003e finalizer. It creates a JWT from the subject object with standard claims, setting the \u003ccode\u003esub\u003c/code\u003e claim to the subject’s ID. The key for signing the JWT comes from a key store we’ll configure later.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese two lines define the \u003ccode\u003enoop\u003c/code\u003e finalizer, which we’ll use for public endpoints.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e9\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we set up two \u003ccode\u003eredirect\u003c/code\u003e error handlers: one redirects to the \u003ccode\u003e/oauth2/start\u003c/code\u003e endpoint with a deep link to the current URL, and the other redirects to Google with the search query \u0026#34;access denied\u0026#34;.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e10\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWith all mechanisms defined, we configure our first rule - the \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e. This rule applies if no other rules match the request and serves as a \u003ca href=\"/docs/concepts/rules/#_default_rule_inheritance\"\u003ebase\u003c/a\u003e for defining regular (upstream service-specific) rules as well. It sets up a default \u003ca href=\"/docs/concepts/pipelines/#_authentication_authorization_pipeline\"\u003eauthentication \u0026amp; authorization pipeline\u003c/a\u003e that rejects all requests using the \u003ccode\u003edeny_all\u003c/code\u003e authenticator. This rejection triggers the \u003ccode\u003eredirect_to_error_page\u003c/code\u003e error handler. If a regular rule overrides this authenticator, a JWT is created using the \u003ccode\u003ejwt\u003c/code\u003e finalizer.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e11\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe last few lines configure the \u003ca href=\"/docs/rules/providers/#_filesystem\"\u003e\u003ccode\u003efile_system\u003c/code\u003e\u003c/a\u003e provider, which loads regular rules from the file system and watches for changes. This allows you to modify the rules while testing.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a file named \u003ccode\u003esigner.pem\u003c/code\u003e and add the following content to it. This file should also be placed in the root directory and will act as our key store, containing the private key referenced in the configuration above.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"s\"\u003e-----BEGIN EC PRIVATE KEY-----\u003c/span\u003e\n\u003cspan class=\"s\"\u003eMIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy\u003c/span\u003e\n\u003cspan class=\"s\"\u003e1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI\u003c/span\u003e\n\u003cspan class=\"s\"\u003ezlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X\u003c/span\u003e\n\u003cspan class=\"s\"\u003eXVwR/5tokqFVrFxt/5c1x7VdccF4nNM=\u003c/span\u003e\n\u003cspan class=\"s\"\u003e-----END EC PRIVATE KEY-----\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nDo not use it for purposes beyond this tutorial!\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNext, we’ll create rules for our main service - the one exposing \u003ccode\u003e/\u003c/code\u003e, \u003ccode\u003e/user\u003c/code\u003e and the \u003ccode\u003e/admin\u003c/code\u003e endpoints. To do this, create a file named \u003ccode\u003eupstream-rules.yaml\u003c/code\u003e in the \u003ccode\u003erules\u003c/code\u003e directory with the following content:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:public\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/favicon.ico\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\n\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:protected\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/user\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/admin\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauth\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRequest.URL.Path == \u0026#39;/admin\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ehas(Subject.Attributes.groups) \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;role:admin\u0026#34; in Subject.Attributes.groups\u003c/span\u003e\n \u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eUser is not admin\u003c/span\u003e\n \u003cspan class=\"na\"\u003eon_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect_to_idp\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) == authentication_error \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eRequest.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;)\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect_to_error_page\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) == authorization_error \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eRequest.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;)\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis first rule is for the \u003ccode\u003e/\u003c/code\u003e endpoint. It instructs heimdall to pass requests to this endpoint directly through to our upstream service.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe second rule ensures that the \u003ccode\u003e/user\u003c/code\u003e endpoint is only accessible to authenticated users, while the \u003ccode\u003e/admin\u003c/code\u003e endpoint is only accessible to users with the \u003ccode\u003eadmin\u003c/code\u003e role configured in our IDP.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNext, we’ll create a rule for the OAuth2-Proxy, placed behind heimdall and publicly exposing only certain endpoints. Create a new file named \u003ccode\u003eoauth2-proxy-rules.yaml\u003c/code\u003e in the \u003ccode\u003erules\u003c/code\u003e directory with the following content:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2-proxy:public\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/oauth2/start\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/oauth2/callback\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2-proxy:4180\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNext, we’ll create a database initialization script to set up a database for Keycloak. In the \u003ccode\u003einitdb\u003c/code\u003e directory, create a file named \u003ccode\u003einitdb.sh\u003c/code\u003e with the following content, and make it executable by running \u003ccode\u003echmod +x initdb.sh\u003c/code\u003e:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"c\"\u003e#!/bin/bash\u003c/span\u003e\n\u003cspan class=\"nb\"\u003eset\u003c/span\u003e \u003cspan class=\"nt\"\u003e-e\u003c/span\u003e\n\npsql \u003cspan class=\"nt\"\u003e-v\u003c/span\u003e \u003cspan class=\"nv\"\u003eON_ERROR_STOP\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e1 \u003cspan class=\"nt\"\u003e--username\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e$POSTGRES_USER\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;\u0026lt;-\u003c/span\u003e\u003cspan class=\"no\"\u003eEOSQL\u003c/span\u003e\u003cspan class=\"sh\"\u003e\n CREATE USER keycloak WITH PASSWORD \u0026#39;keycloak\u0026#39;;\n CREATE DATABASE keycloak OWNER keycloak;\n\u003c/span\u003e\u003cspan class=\"no\"\u003eEOSQL\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNow, let’s bring everything together using a Docker Compose file. Create a file named \u003ccode\u003edocker-compose.yaml\u003c/code\u003e in the root directory with the following content:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edadrus/heimdall:dev\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e9090:4455\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eserve proxy --c /etc/heimdall/config.yaml --insecure\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./heimdall-config.yaml:/etc/heimdall/config.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./rules:/etc/heimdall/rules:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./signer.pem:/etc/heimdall/signer.pem:ro\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eupstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003econtainous/whoami:latest\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e--port=8081\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eoauth2-proxy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003edepends_on\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak\u003c/span\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003equay.io/oauth2-proxy/oauth2-proxy:v7.6.0-amd64\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e--http-address\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e0.0.0.0:4180\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenvironment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_CLIENT_ID\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eplaceholder\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_CLIENT_SECRET\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eplaceholder\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_REDIRECT_URL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://127.0.0.1:9090/oauth2/callback\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_PROVIDER\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak-oidc\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_SKIP_PROVIDER_BUTTON\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_COOKIE_SECRET\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecure!!!!!!\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_COOKIE_NAME\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSESSION\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_WHITELIST_DOMAINS\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1:9090\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_OIDC_ISSUER_URL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://keycloak:8080/realms/test\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_EMAIL_DOMAINS\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e*\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_OIDC_EXTRA_AUDIENCES\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccount\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_LOGIN_URL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://127.0.0.1:8080/realms/test/protocol/openid-connect/auth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e(9)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_OIDC_JWKS_URL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://keycloak:8080/realms/test/protocol/openid-connect/certs\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_REDEEM_URL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://keycloak:8080/realms/test/protocol/openid-connect/token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_INSECURE_OIDC_SKIP_ISSUER_VERIFICATION\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_SKIP_OIDC_DISCOVERY\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003ekeycloak\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e(10)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003equay.io/keycloak/keycloak:25.0.4\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003estart-dev\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e--http-port\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e8080\u0026#34;\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e8080:8080\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenvironment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_HOSTNAME\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_HOSTNAME_PORT\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e8080\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_HOSTNAME_STRICT_BACKCHANNEL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etrue\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKEYCLOAK_ADMIN\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eadmin\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKEYCLOAK_ADMIN_PASSWORD\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eadmin\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_HEALTH_ENABLED\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etrue\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_LOG_LEVEL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003einfo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_DB_URL_HOST\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003epostgresql\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_DB\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003epostgres\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_DB_USERNAME\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_DB_PASSWORD\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak\u003c/span\u003e\n \u003cspan class=\"na\"\u003edepends_on\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003epostgresql\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003epostgresql\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e(11)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003epostgres:13.11\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003evolume\u003c/span\u003e\n \u003cspan class=\"na\"\u003esource\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003epostgres-db\u003c/span\u003e\n \u003cspan class=\"na\"\u003etarget\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/var/lib/postgresql/data\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread_only\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./initdb:/docker-entrypoint-initdb.d\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenvironment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePOSTGRES_USER=postgres\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePOSTGRES_PASSWORD=postgres\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epostgres-db\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we configure heimdall to use the previously defined configuration.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWe’re using the \u003ccode\u003e--insecure\u003c/code\u003e flag here to simplify our setup, which disables enforcement of some security settings you can learn about more \u003ca href=\"/docs/operations/security/#_defaults\"\u003ehere\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis section sets up the main service that we’ll be protecting.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis section defines the OAuth2-Proxy configuration, which heimdall will use to handle the Authorization Code Grant flow and manage the authentication session with a \u003ccode\u003eSESSION\u003c/code\u003e cookie.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe client ID and client secret values are placeholders. We will configure these in Keycloak.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSince the redirect URI, exposed as \u003ccode\u003e/oauth2/callback\u003c/code\u003e, is behind heimdall, we use the publicly accessible endpoint here.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe URL of the issuer that OAuth2-Proxy will use. We’ll create a corresponding realm in Keycloak to match this configuration.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe following two lines are required as we don’t want keycloak to verify the email addresses of the users we’ll be creating, and we want to allow any email domain.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eTo avoid creating a mapper to let Keycloak set a proper \u003ccode\u003eaud\u003c/code\u003e claim value, we allow the usage of \u003ccode\u003eaccount\u003c/code\u003e audience set by Keycloak by default.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e9\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines are only required as Keycloak is part of our docker compose setup, and we have to use different domain names while communicating with it.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e10\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis section sets up Keycloak.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e11\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eFinally, this section configures our database.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_create_a_realm_and_a_client_in_keycloak\"\u003eCreate a Realm and a Client in Keycloak\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith the above configuration in place, follow these steps to start Keycloak and the database, initialize both, and create the OAuth2-Proxy client:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eIn the root directory, run \u003ccode\u003edocker compose up postgresql keycloak\u003c/code\u003e. Wait until the database is initialized and Keycloak has started.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOpen your browser and go to \u003ccode\u003ehttp://127.0.0.1:8080\u003c/code\u003e. Log in using the admin credentials (both the username and password are set to \u003ccode\u003eadmin\u003c/code\u003e in our setup).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a Realm named \u003ccode\u003etest\u003c/code\u003e. For detailed instructions, refer to the Keycloak documentation on \u003ca href=\"https://www.keycloak.org/docs/latest/server_admin/index.html#proc-creating-a-realm_server_administration_guide\"\u003e creating a realm\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWithin the \u003ccode\u003etest\u003c/code\u003e realm, create an OpenID Client. Follow the Keycloak documentation on \u003ca href=\"https://www.keycloak.org/docs/latest/server_admin/index.html#proc-creating-oidc-client_server_administration_guide\"\u003ecreating an OIDC client\u003c/a\u003e. Enable \u0026#34;Client authentication\u0026#34; and \u0026#34;Standard Flow\u0026#34;, set \u003ccode\u003ehttp://127.0.0.1:9090/oauth2/callback\u003c/code\u003e as the \u0026#34;Valid Redirect URI\u0026#34; and \u003ccode\u003ehttp://127.0.0.1:9090/\u003c/code\u003e as the \u0026#34;Home URL\u0026#34; and \u0026#34;Valid post logout redirect URIs\u0026#34; and note the \u0026#34;Client ID\u0026#34; and \u0026#34;Client Secret\u0026#34; (later can be found under the \u0026#34;Credentials\u0026#34; tab after completing the client creation wizard); we will use these to complete the OAuth2-Proxy configuration in our Docker Compose file.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eStop the docker compose setup with \u003ccode\u003eCTRL-C\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_update_oauth2_proxy_configuration\"\u003eUpdate OAuth2-Proxy Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWe can now finalize the configuration and use the proper client id and secret for OAuth2-Proxy\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate the \u003ccode\u003eOAUTH2_PROXY_CLIENT_ID\u003c/code\u003e and \u003ccode\u003eOAUTH2_PROXY_CLIENT_SECRET\u003c/code\u003e in the configuration of the OAuth2-Proxy in the docker compose file with the \u0026#34;Client ID\u0026#34; and \u0026#34;Client Secret\u0026#34; values from Keycloak\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_use_the_setup\"\u003eUse the Setup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWe now have almost everything set up. The final step is to create a few users, including at least one with the \u003ccode\u003eadmin\u003c/code\u003e role assigned.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eIn the root directory, run \u003ccode\u003edocker compose up\u003c/code\u003e. Wait until all services are up and running.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOpen your browser and navigate to \u003ccode\u003ehttp://127.0.0.1:8080\u003c/code\u003e. Log in using the admin credentials (both username and password are set to \u003ccode\u003eadmin\u003c/code\u003e).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eSelect the \u003ccode\u003etest\u003c/code\u003e realm and create an \u003ccode\u003eadmin\u003c/code\u003e group with a role named \u003ccode\u003eadmin\u003c/code\u003e assigned to it. For guidance, refer to the Keycloak documentation on creating \u003ca href=\"https://www.keycloak.org/docs/latest/server_admin/index.html#proc-managing-groups_server_administration_guide\"\u003eGroups\u003c/a\u003e and \u003ca href=\"https://www.keycloak.org/docs/latest/server_admin/index.html#proc-creating-realm-roles_server_administration_guide\"\u003eRoles\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate several users following the Keycloak documentation on \u003ca href=\"https://www.keycloak.org/docs/latest/server_admin/index.html#proc-creating-user_server_administration_guide\"\u003emanaging users\u003c/a\u003e, and assign some of them to the \u003ccode\u003eadmin\u003c/code\u003e group. Disable email verification during user creation to avoid sending verification emails to potentially non-existent addresses.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNow, let’s test the setup:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eNavigate to \u003ccode\u003ehttp://127.0.0.1:9090/\u003c/code\u003e. You should see some text similar to the one shown below. This text is the response from our upstream service, which echoes back everything the browser sends in its request.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003eHostname: 39f1815dd8ac\nIP: 127.0.0.1\nIP: ::1\nIP: 172.31.0.3\nRemoteAddr: 172.31.0.2:37908\nGET / HTTP/1.1\nHost: upstream:8081\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8\nAccept-Encoding: gzip, deflate, br, zstd\nAccept-Language: de,en-US;q=0.7,en;q=0.3\nDnt: 1\nForwarded: for=172.31.0.1;host=127.0.0.1:9090;proto=http\nPriority: u=0, i\nSec-Fetch-Dest: document\nSec-Fetch-Mode: navigate\nSec-Fetch-Site: none\nSec-Fetch-User: ?1\nUpgrade-Insecure-Requests: 1\nX-Trp-Catalog: de\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAttempt to access the \u003ccode\u003ehttp://127.0.0.1:9090/user\u003c/code\u003e endpoint. You should be redirected to the Keycloak login page. Log in with any of the users you configured. After logging in, you should be redirected back to \u003ccode\u003ehttp://127.0.0.1:9090/user\u003c/code\u003e, where you’ll see some text similar to the one shown below. This indicates that the request hit the \u003ccode\u003e/user\u003c/code\u003e endpoint of our upstream service. You should also see a JWT token in the \u003ccode\u003eAuthorization\u003c/code\u003e header, which is the result of the JWT finalizer we configured.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003eHostname: 39f1815dd8ac\nIP: 127.0.0.1\nIP: ::1\nIP: 172.31.0.3\nRemoteAddr: 172.31.0.2:37908\nGET /user HTTP/1.1\nHost: upstream:8081\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8\nAccept-Encoding: gzip, deflate, br, zstd\nAccept-Language: de,en-US;q=0.7,en;q=0.3\nAuthorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJhdHRycyI6eyJlbWFpbCI6InRlc3QxQGV4YW1wbGUuY29tIiwiZ3JvdXBzIjpbInJvbGU6ZGVmYXVsdC1yb2xlcy10ZXN0Iiwicm9sZTpvZmZsaW5lX2FjY2VzcyIsInJvbGU6YWRtaW4iLCJyb2xlOnVtYV9hdXRob3JpemF0aW9uIiwicm9sZTphY2NvdW50Om1hbmFnZS1hY2NvdW50Iiwicm9sZTphY2NvdW50Om1hbmFnZS1hY2NvdW50LWxpbmtzIiwicm9sZTphY2NvdW50OnZpZXctcHJvZmlsZSJdLCJwcmVmZXJyZWRVc2VybmFtZSI6InRlc3QxIiwidXNlciI6IjQ5ZWE3Mjk3LWI0NzgtNDcxNC05NjM2LWQ5ZTk3ZmVkZmNhOSJ9LCJleHAiOjE3MjY0NjkyMTAsImlhdCI6MTcyNjQ2ODkxMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJkODg3Y2Q3MC1iYzhlLTQ2MTItODYzNS1lYTYwYjU1ZmU3MzciLCJuYmYiOjE3MjY0Njg5MTAsInN1YiI6IjQ5ZWE3Mjk3LWI0NzgtNDcxNC05NjM2LWQ5ZTk3ZmVkZmNhOSJ9.JLS__gH0wEHwB07DV9Rcrm9mo1xfXpqHoC8pbZ523KHV7QO3n2jrauiB4fVggB5DPe4tTUrp8X1e4nePXPniJyACyC7gmoBX5PJTbUPlalsw0WKOfYOcYXjwJDakId5r\nCookie: SESSION=S77dk6NGQyyreWQ1enWRSCSP...wBsNTlidPgTBahs=\nDnt: 1\nForwarded: for=172.31.0.1;host=127.0.0.1:9090;proto=http\nPriority: u=0, i\nSec-Fetch-Dest: document\nSec-Fetch-Mode: navigate\nSec-Fetch-Site: none\nSec-Fetch-User: ?1\nUpgrade-Insecure-Requests: 1\nX-Trp-Catalog: de\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eTry accessing the \u003ccode\u003ehttp://127.0.0.1:9090/admin\u003c/code\u003e endpoint with both a user not in the \u003ccode\u003eadmin\u003c/code\u003e group and a user from the \u003ccode\u003eadmin\u003c/code\u003e group. The user not in the \u003ccode\u003eadmin\u003c/code\u003e group should see the \u0026#34;access denied\u0026#34; page, while the user from the \u003ccode\u003eadmin\u003c/code\u003e group should be able to access the endpoint and see the echoed response from our upstream service.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nTo \u0026#34;logout\u0026#34; the user, just delete the cookies for \u003ccode\u003ehttp://127.0.0.1:9090\u003c/code\u003e using the Web-Developer Tools of your browser.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAttempts to access any not exposed endpoints, like \u003ccode\u003ehttp://127.0.0.1:9090/foo\u003c/code\u003e will always result in the \u0026#34;access denied\u0026#34; page.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cleanup\"\u003eCleanup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eJust stop the environment with \u003ccode\u003eCTRL-C\u003c/code\u003e and delete the created files. If you started docker compose in the background, tear the environment down with \u003ccode\u003edocker-compose down\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","Authentication Protocols \u0026 Services"],"tags":null,"title":"First-Party Authentication with OpenID Connect","url":"/guides/authn/oidc_first_party_auth/"},{"categories":null,"content":" Configuration in heimdall can refer to two different things:\nthe static startup configuration, which is the scope of this document and\nthe configuration of rules, respectively rule sets, which you can find here.\nElements in the static configuration set up the services, like the main service, which basically defines the main entry point, heimdall will listen to for the actual access control decision purposes, the observability capabilities, like logging, the mechanism catalogue, the default rule, as well as the rule providers (these elements are not expected to change often).\nThe rule set contains everything that defines how the requests are handled by heimdall for your system. This configuration can change and is seamlessly hot-reloaded, without any request interruption or connection loss.\nOverview There are two different, not mutually exclusive (you can combine them), ways to define static configuration options in Heimdall:\nin a configuration file (only YAML is supported as format)\nas environment variables\nThe evaluation happens also in the order stated above. That also means, you can always overwrite configuration options defined in a configuration file with corresponding environment variables.\nIf no configuration is provided, heimdall will set useful defaults. These are however not enough, as heimdall doesn’t know your context - which mechanisms are required for the one or the other of your upstream services. So, you’ll not really be able to use heimdall as all requests will be answered with an HTTP 405 Method Not Allowed response code.\nConfiguration File At start up, heimdall searches for static configuration in a file named heimdall.yaml in\n/etc/heimdall\n$HOME/.config\nthe current working directory\nYou can also override this using the config argument: heimdall --config \u0026lt;path-to-your-config-file\u0026gt;.\nThe values in the configuration file can also make use of environment variables. Access to these happens using Bash syntax. Following expressions are supported:\n${var} - Value of $var\n${var=default} - If $var is not set, evaluate expression as default\n${var:=default} - If $var is not set or is empty, evaluate expression as default\nExample 1. Possible minimal fully working configuration The configuration below defines a default rule which lets heimdall create a JSON Web Token (JWT) with sub claim set to anonymous for every request on every URL for the HTTP methods GET and POST. The JWT itself will be put into the Authorization header as a bearer token.\nlog: level: info mechanisms: authenticators: - id: anonymous_authenticator type: anonymous finalizers: - id: create_jwt type: jwt config: signer: key_store: path: /etc/heimdall/signer.pem default_rule: execute: - authenticator: anonymous_authenticator - finalizer: create_jwt Example 2. Configuration with a mechanism defined using environment variables substitution mechanisms: authenticators: - id: hydra_authenticator type: oauth2_introspection config: introspection_endpoint: url: https://hydra:4445/oauth2/introspect auth: type: basic_auth config: user: ${INTROSPECT_EP_USER} password: ${INTROSPECT_EP_PASSWORD} finalizers: - id: create_jwt type: jwt config: signer: key_store: path: ${SIGNER_KEY_STORE_FILE} Environment Variables Every configuration property, which can be defined in a configuration file can also be defined as environment variable. Following rules apply:\nIf not specified while starting heimdall, all variables start with HEIMDALLCFG_ prefix.\nIf for whatever reason, your environment configuration contains variables starting with HEIMDALLCFG_, which do not define heimdall specific configuration, heimdall will refuse starting if such configuration variable clashes (has an unexpected type) with heimdall’s configuration properties (even for environment variables, the configuration is type safe). You can overcome such situation, by ether renaming such variables, or, if this is not possible, make use of the --env-config-prefix flag with heimdall’s serve command. Properties in a hierarchy are separated by _\nE.g. the log level can be set to info in a config file as also shown in the above example with\nlog: level: info and using an environment variable with\nHEIMDALLCFG_LOG_LEVEL=info Array entries must be defined using _\u0026lt;IDX\u0026gt;[_], with IDX being the index of the array starting with 0 and _ in brackets being only required, if the value of the configured element has a structure/hierarchy.\nE.g. the trusted_proxies property of the main service can be configured in a config file as\nserve: trusted_proxies: - 192.168.1.0/24 - 192.168.2.0/24 and using environment variables with\nHEIMDALLCFG_SERVE_TRUSTED__PROXIES_0=192.168.1.0/24 HEIMDALLCFG_SERVE_TRUSTED__PROXIES_0=192.168.2.0/24 For structured configuration, like the definition of the authenticators in the example above\nmechanisms: authenticators: - id: anonymous_authenticator type: anonymous The corresponding environment variables would be\nHEIMDALLCFG_MECHANISMS_AUTHENTICATORS_0_ID=anonymous_authenticator HEIMDALLCFG_MECHANISMS_AUTHENTICATORS_0_TYPE=anonymous If a name of a property has _ it must be escaped with an additional _.\nE.g. by setting the span processor to simple, you can instruct heimdall to synchronously export the created spans via configured exporters.\ntracing: span_processor: simple and using the environment variables with\nHEIMDALLCFG_TRACING_SPAN__PROCESSOR=simple ","description":"This page explains the available configuration options in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration in heimdall can refer to two different things:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ethe static startup configuration, which is the scope of this document and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe configuration of rules, respectively rule sets, which you can find \u003ca href=\"/docs/rules/rule_sets/\"\u003ehere\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eElements in the static configuration set up the services, like the \u003ca href=\"/docs/services/main/\"\u003emain service\u003c/a\u003e, which basically defines the main entry point, heimdall will listen to for the actual access control decision purposes, the observability capabilities, like \u003ca href=\"/docs/operations/observability/#_logging\"\u003elogging\u003c/a\u003e, the \u003ca href=\"/docs/concepts/mechanisms/\"\u003emechanism catalogue\u003c/a\u003e, the \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e, as well as the \u003ca href=\"/docs/rules/providers/\"\u003erule providers\u003c/a\u003e (these elements are not expected to change often).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe rule set contains everything that defines how the requests are handled by heimdall for your system.\nThis configuration can change and is seamlessly hot-reloaded, without any request interruption or connection loss.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_overview\"\u003eOverview\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere are two different, not mutually exclusive (you can combine them), ways to define static configuration options in Heimdall:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003ein a \u003ca href=\"#_configuration_file\"\u003econfiguration file\u003c/a\u003e (only \u003ca href=\"https://yaml.org/spec/1.2.2/\"\u003eYAML\u003c/a\u003e is supported as format)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eas \u003ca href=\"#_environment_variables\"\u003eenvironment variables\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe evaluation happens also in the order stated above.\nThat also means, you can always overwrite configuration options defined in a configuration file with corresponding environment variables.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf no configuration is provided, heimdall will set useful defaults.\nThese are however not enough, as heimdall doesn’t know your context - which mechanisms are required for the one or the other of your upstream services.\nSo, you’ll not really be able to use heimdall as all requests will be answered with an HTTP \u003ccode\u003e405 Method Not Allowed\u003c/code\u003e response code.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration_file\"\u003eConfiguration File\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAt start up, heimdall searches for static configuration in a file named \u003ccode\u003eheimdall.yaml\u003c/code\u003e in\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/etc/heimdall\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e$HOME/.config\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe current working directory\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can also override this using the \u003ccode\u003econfig\u003c/code\u003e argument: \u003ccode\u003eheimdall --config \u0026lt;path-to-your-config-file\u0026gt;\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe values in the configuration file can also make use of environment variables. Access to these happens using Bash syntax. Following expressions are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e${var}\u003c/code\u003e - Value of \u003ccode\u003e$var\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e${var=default}\u003c/code\u003e - If \u003ccode\u003e$var\u003c/code\u003e is not set, evaluate expression as \u003ccode\u003edefault\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e${var:=default}\u003c/code\u003e - If \u003ccode\u003e$var\u003c/code\u003e is not set or is empty, evaluate expression as \u003ccode\u003edefault\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Possible minimal fully working configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration below defines a \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e which lets heimdall create a JSON Web Token (JWT) with \u003ccode\u003esub\u003c/code\u003e claim set to \u003ccode\u003eanonymous\u003c/code\u003e for every request on every URL for the HTTP methods GET and POST.\nThe JWT itself will be put into the \u003ccode\u003eAuthorization\u003c/code\u003e header as a bearer token.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003einfo\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/signer.pem\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003edefault_rule\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous_authenticator\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Configuration with a mechanism defined using environment variables substitution\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehydra_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_introspection\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eintrospection_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://hydra:4445/oauth2/introspect\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${INTROSPECT_EP_USER}\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${INTROSPECT_EP_PASSWORD}\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${SIGNER_KEY_STORE_FILE}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_environment_variables\"\u003eEnvironment Variables\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEvery configuration property, which can be defined in a \u003ca href=\"#_configuration_file\"\u003econfiguration file\u003c/a\u003e can also be defined as environment variable.\nFollowing rules apply:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIf not specified while starting heimdall, all variables start with \u003ccode\u003eHEIMDALLCFG_\u003c/code\u003e prefix.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf for whatever reason, your environment configuration contains variables starting with \u003ccode\u003eHEIMDALLCFG_\u003c/code\u003e, which do not define heimdall specific configuration, heimdall will refuse starting if such configuration variable clashes (has an unexpected type) with heimdall’s configuration properties (even for environment variables, the configuration is type safe).\nYou can overcome such situation, by ether renaming such variables, or, if this is not possible, make use of the \u003ccode\u003e--env-config-prefix\u003c/code\u003e flag with heimdall’s \u003ccode\u003eserve\u003c/code\u003e command.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eProperties in a hierarchy are separated by \u003ccode\u003e_\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g. the log level can be set to \u003ccode\u003einfo\u003c/code\u003e in a config file as also shown in the above example with\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003einfo\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eand using an environment variable with\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eHEIMDALLCFG_LOG_LEVEL\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003einfo\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eArray entries must be defined using \u003ccode\u003e_\u0026lt;IDX\u0026gt;[_]\u003c/code\u003e, with \u003ccode\u003eIDX\u003c/code\u003e being the index of the array starting with \u003ccode\u003e0\u003c/code\u003e and \u003ccode\u003e_\u003c/code\u003e in brackets being only required, if the value of the configured element has a structure/hierarchy.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g. the \u003ccode\u003etrusted_proxies\u003c/code\u003e property of the \u003ca href=\"/docs/services/main/\"\u003emain service\u003c/a\u003e can be configured in a config file as\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eserve\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etrusted_proxies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e192.168.1.0/24\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e192.168.2.0/24\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eand using environment variables with\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eHEIMDALLCFG_SERVE_TRUSTED__PROXIES_0\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e192.168.1.0/24\n\u003cspan class=\"nv\"\u003eHEIMDALLCFG_SERVE_TRUSTED__PROXIES_0\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e192.168.2.0/24\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor structured configuration, like the definition of the authenticators in the example above\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe corresponding environment variables would be\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eHEIMDALLCFG_MECHANISMS_AUTHENTICATORS_0_ID\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003eanonymous_authenticator\n\u003cspan class=\"nv\"\u003eHEIMDALLCFG_MECHANISMS_AUTHENTICATORS_0_TYPE\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003eanonymous\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf a name of a property has \u003ccode\u003e_\u003c/code\u003e it must be escaped with an additional \u003ccode\u003e_\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g. by setting the span processor to \u003ccode\u003esimple\u003c/code\u003e, you can instruct heimdall to synchronously export the created spans via configured exporters.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003espan_processor\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esimple\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eand using the environment variables with\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eHEIMDALLCFG_TRACING_SPAN__PROCESSOR\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003esimple\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Operations"],"tags":null,"title":"Configuration ","url":"/docs/operations/configuration/"},{"categories":null,"content":" Usage Patterns heimdall [command] [flags] [arguments] Use heimdall help to get overview about available commands, respectively heimdall [command] help for help on any command.\nFlag’s usage:\n# set flag_argument to flag(s) heimdall [--flag=flag_argument] [-f [flag_argument]] E.g.\nheimdall validate config -c config.yaml Commands completion\nGenerates the autocompletion script for the specified shell.\nhealth\nCalls heimdall’s healthcheck endpoint to verify the status of the deployment.\nhelp\nProvides an overview about the available commands and their descriptions.\nserve\nStarts heimdall in the decision, or the reverse proxy operation mode.\nvalidate\nValidates heimdall configuration, like rules or the actual configuration.\n","description":"Here, you can find the description of heimdall's command line interface.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_usage_patterns\"\u003eUsage Patterns\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eheimdall \u003cspan class=\"o\"\u003e[\u003c/span\u003e\u003cspan class=\"nb\"\u003ecommand\u003c/span\u003e\u003cspan class=\"o\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e[\u003c/span\u003eflags] \u003cspan class=\"o\"\u003e[\u003c/span\u003earguments]\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUse \u003ccode\u003eheimdall help\u003c/code\u003e to get overview about available commands, respectively \u003ccode\u003eheimdall [command] help\u003c/code\u003e for help on any command.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFlag’s usage:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"c\"\u003e# set flag_argument to flag(s)\u003c/span\u003e\nheimdall \u003cspan class=\"o\"\u003e[\u003c/span\u003e\u003cspan class=\"nt\"\u003e--flag\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003eflag_argument] \u003cspan class=\"o\"\u003e[\u003c/span\u003e\u003cspan class=\"nt\"\u003e-f\u003c/span\u003e \u003cspan class=\"o\"\u003e[\u003c/span\u003eflag_argument]]\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eheimdall validate config \u003cspan class=\"nt\"\u003e-c\u003c/span\u003e config.yaml\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_commands\"\u003eCommands\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ecompletion\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eGenerates the autocompletion script for the specified shell.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ehealth\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCalls heimdall’s healthcheck endpoint to verify the status of the deployment.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ehelp\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eProvides an overview about the available commands and their descriptions.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eserve\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eStarts heimdall in the decision, or the reverse proxy operation mode.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003evalidate\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eValidates heimdall configuration, like rules or the actual configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Operations"],"tags":null,"title":"CLI","url":"/docs/operations/cli/"},{"categories":null,"content":" Logging Heimdall’s implementation uses zerolog - Zero Allocation JSON Logger, which can however also log in plain text. All emitted log statements include information related to distributed tracing (if tracing is enabled) so that not only log statements can be correlated to traces, but also all log statements belonging to single request/transaction can be correlated as well.\nConfiguration Logging configuration can be adjusted in the log property of heimdall’s configuration and supports following properties.\nformat: string (optional)\nWith text and gelf being the available formats. text is the default format. And gelf defines a JSON format adhering to GELF.\nUsage of text (default) format is not recommended for production deployments as it requires more computational resources and is hence slow. Example 1. Configuring logging to emit logs using GELD format. log: format: gelf level: string (optional)\nFollowing log levels are available: trace, debug, info, warn, error, fatal, panic and disabled. The last one effectively disables logging. You usually do not want to do this. By default, the level is set to error.\ndebug and trace log levels are not meant for production as setting log level to one of these will result in a high log verbosity and also affect performance pretty much. Both are only meant for setup analysis and debugging! trace log level will also dump all incoming and outgoing HTTP requests and responses, as well as the contents of objects used in templates. That dump is unedited. That means sensitive data will be available in logs. Due to some limitations of the GRPC framework capabilities, setting log level to trace will not dump GRPC requests and responses. If you need these for analysis purposes (e.g. when debugging the integration with envoy proxy), you’ll have to set GODEBUG as well as the GRPC_GO_LOG_VERBOSITY_LEVEL and GRPC_GO_LOG_SEVERITY_LEVEL environment variables. Example 2. Configuring logging to emit logs in debug level. log: level: debug Regular Log Events If you configure heimdall to log in text format, you can expect output similar to the one shown below:\n2022-08-03T12:51:48+02:00 INF Opentelemetry tracing initialized. 2022-08-03T12:51:48+02:00 INF Instantiating in memory cache 2022-08-03T12:51:48+02:00 DBG Creating rule set event queue. 2022-08-03T12:51:48+02:00 INF Loading pipeline definitions 2022-08-03T12:51:48+02:00 DBG Loading definitions for authenticators 2022-08-03T12:51:48+02:00 DBG Loading pipeline definition id=anonymous_authenticator type=anonymous ... 2022-08-03T12:51:52+02:00 DBG Decision endpoint called 2022-08-03T12:51:52+02:00 DBG Executing default rule 2022-08-03T12:51:52+02:00 DBG Authenticating using anonymous authenticator 2022-08-03T12:51:52+02:00 DBG Finalizing using JWT finalizer 2022-08-03T12:51:52+02:00 DBG Generating new JWT 2022-08-03T12:51:52+02:00 DBG Finalizing request Usage of this format is not recommended for production deployments as it requires more computational resources and is hence slow. Otherwise, if you configure it to use gelf (see GELF for format details) format, the output will look as follows:\n{\u0026#34;_level_name\u0026#34;: \u0026#34;INFO\u0026#34;, \u0026#34;version\u0026#34;:\u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 6, \u0026#34;short_message\u0026#34;: \u0026#34;Opentracing tracer initialized.\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;INFO\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 6, \u0026#34;short_message\u0026#34;: \u0026#34;Instantiating in memory cache\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 7, \u0026#34;short_message\u0026#34;: \u0026#34;Creating rule set event queue.\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;INFO\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 6, \u0026#34;short_message\u0026#34;: \u0026#34;Loading pipeline definitions\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 7,\u0026#34;short_message\u0026#34;: \u0026#34;Loading definitions for authenticators\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;id\u0026#34;: \u0026#34;anonymous_authenticator\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;anonymous\u0026#34;,\u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 7, \u0026#34;short_message\u0026#34;: \u0026#34;Loading pipeline definition\u0026#34;} ... {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Decision endpoint called\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;:1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Executing default rule\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;:\u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;:1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Authenticating using anonymous authenticator\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Finalizing using JWT finalizer\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Generating new JWT\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Finalizing request\u0026#34;} Each log statement does also include the following fields in both log formats for incoming requests if tracing is enabled:\n_trace_id - The trace id as defined by OpenTelemetry.\n_span_id - The span id as defined by OpenTelemetry of the current transaction.\n_parent_id - The span id of the callee, which started the given transaction. Only present if the callee set the corresponding tracing header.\nAccess Log Events In addition to regular logs, heimdall emits access logs. These events are always emitted regardless the configured log level and the log level of these events in the log output is always INFO.\nEach request to any of heimdall’s endpoints will result in two access events:\nevent describing the start of the transaction, and an\nevent describing the finalization of the transaction.\nFollowing are the fields, which are always set for both events:\n_tx_start - Timestamp in Unix epoch format, when the transaction started.\n_client_ip - The IP of the client of the request.\nIf the event has been emitted for an HTTP request, following fields are set as well:\n_http_method - The HTTP method used by the client while calling heimdall’s endpoint.\n_http_path - The used HTTP path.\n_http_user_agent - The agent used by the client. The value is taken from the HTTP \u0026#34;User-Agent\u0026#34; header.\n_http_host - The host part of the URI, the client is using while communicating with Heimdall.\n_http_scheme - The scheme part of the URI, the client is using while communicating with Heimdall.\nIf the event has been emitted for a GRPC request, following fields are set:\n_grpc_method - The full GRPC method used.\nIf the request comes from an intermediary, like e.g. an API Gateway and heimdall is configured to trust that \u0026#34;proxy\u0026#34; (see trusted_proxies configuration), then following fields will be part of the events as well if the corresponding HTTP headers were sent.\n_http_x_forwarded_proto - The value of the \u0026#34;X-Forwarded-Proto\u0026#34; header.\n_http_x_forwarded_host - The value of the \u0026#34;X-Forwarded-Host\u0026#34; header.\n_http_x_forwarded_uri - The value of the \u0026#34;X-Forwarded-Uri\u0026#34; header.\n_http_x_forwarded_for - The value of the \u0026#34;X-Forwarded-For\u0026#34; header.\n_http_forwarded - The value of the \u0026#34;Forwarded\u0026#34; header.\nFollowing are the fields, which are set in the transaction finalization event in addition:\n_body_bytes_sent - The length of the response body.\n_tx_duration_ms - The duration of the transaction in milliseconds. If heimdall is operated in proxy mode, it will also include the time used to communicate with the upstream service.\n_access_granted - Set either to true or false, indicating whether heimdall granted access or not.\n_subject - The subject identifier if the access was granted.\n_error - The information about an error, which e.g. led to the denial of the request.\nIf the finalization event has been emitted for an HTTP request, following fields are set as well:\n_http_status_code - The numeric HTTP response status code\nIf the finalization event has been emitted for a GRPC request, following fields are set:\n_grpc_status_code - The numeric GRPC status code.\nFollowing are the fields, which are set if tracing is enabled:\n_trace_id - The trace id as defined by OpenTelemetry.\n_span_id - The span id as defined by OpenTelemetry of the current transaction.\n_parent_id - The span id of the callee, which started the given transaction. Only present if the callee set the corresponding tracing header.\nIf you configure heimdall to log in text format, you can expect output as shown below:\n2022-08-03T12:40:16+02:00 INF TX started _client_ip=127.0.0.1 _http_host=127.0.0.1:4468 _http_method=GET _http_path=/foo _http_scheme=http _http_user_agent=curl/7.74.0 _parent_id=3449bda63ed70206 _span_id=f57c007257fee0ed _trace_id=00000000000000000a5af97bffe6a8a2 _tx_start=1659523216 .... 2022-08-03T12:40:16+02:00 INF TX finished _access_granted=true _body_bytes_sent=0 _client_ip=127.0.0.1 _http_host=127.0.0.1:4468 _http_method=GET _http_path=/foo _http_scheme=http _http_status_code=202 _http_user_agent=curl/7.74.0 _subject=anonymous _parent_id=3449bda63ed70206 _span_id=f57c007257fee0ed _trace_id=00000000000000000a5af97bffe6a8a2 _tx_duration_ms=0 _tx_start=1659523216 Otherwise, if you configure it to use gelf format, the output will look as follows:\n{\u0026#34;_level_name\u0026#34;: \u0026#34;INFO\u0026#34;, \u0026#34;version\u0026#34;:\u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;:\u0026#34;unknown\u0026#34;, \u0026#34;_tx_start\u0026#34;:1659523295, \u0026#34;_client_ip\u0026#34;: \u0026#34;127.0.0.1\u0026#34;, \u0026#34;_http_method\u0026#34;: \u0026#34;GET\u0026#34;, \u0026#34;_http_path\u0026#34;:\u0026#34;/foo\u0026#34;, \u0026#34;_http_user_agent\u0026#34;: \u0026#34;curl/7.74.0\u0026#34;, \u0026#34;_http_host\u0026#34;: \u0026#34;127.0.0.1:4468\u0026#34;, \u0026#34;_http_scheme\u0026#34;: \u0026#34;http\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523295, \u0026#34;level\u0026#34;: 6, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;TX started\u0026#34;} .... {\u0026#34;_level_name\u0026#34;: \u0026#34;INFO\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;_tx_start\u0026#34;: 1659523295, \u0026#34;_client_ip\u0026#34;: \u0026#34;127.0.0.1\u0026#34;, \u0026#34;_http_method\u0026#34;: \u0026#34;GET\u0026#34;, \u0026#34;_http_path\u0026#34;: \u0026#34;/foo\u0026#34;, \u0026#34;_http_user_agent\u0026#34;: \u0026#34;curl/7.74.0\u0026#34;, \u0026#34;_http_host\u0026#34;: \u0026#34;127.0.0.1:4468\u0026#34;, \u0026#34;_http_scheme\u0026#34;: \u0026#34;http\u0026#34;, \u0026#34;_body_bytes_sent\u0026#34;: 0, \u0026#34;_http_status_code\u0026#34;:200, \u0026#34;_tx_duration_ms\u0026#34;:0, \u0026#34;_subject\u0026#34;: \u0026#34;anonymous\u0026#34;, \u0026#34;_access_granted\u0026#34;: true, \u0026#34;timestamp\u0026#34;:1659523295, \u0026#34;level\u0026#34;: 6, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;TX finished\u0026#34;} Tracing Heimdall makes use of OpenTelemetry for distributed tracing to support recording of paths taken by requests and supports all environment variables including the defined values according to OpenTelemetry Environment Variables and OpenTelemetry SDK Configuration specifications. In addition to these environment variables, heimdall defines some additional options, which are described below and can be used to tune the behaviour.\nConfiguration By default, tracing is enabled and can be disabled or slightly tuned in the tracing property of heimdall’s configuration supporting the following properties.\nenabled: boolean (optional)\nBy making use of this property, you can configure heimdall to enable or disable tracing. Defaults to true (tracing enabled).\nExample 3. Disabling tracing. tracing: enabled: false span_processor: string (optional)\nWith simple and batch being the available options. By setting this property, you can define how heimdall shall process the created spans. Defaults to batch. This property is only there, as there is no corresponding setting option via OTEL tracing environment variables available.\nExample 4. Setting the span processor to export completed spans in batches. tracing: span_processor: batch Description of the options:\nsimple - Configures heimdall to synchronously export the created spans via configured exporters. This is not recommended for production use as it is slow and has a high computation resource usage overhead. It might be however good for testing, debugging, or showing examples of other features.\nbatch - Configures heimdall to send completed span batches to the exporter. Recommended setting for production use.\nTracing Context Propagation When a request arrives at heimdall, it will create a trace context object based on the received headers, which according to OTEL are the traceparent and tracestate HTTP headers, defined in W3C Trace Context as well as baggage HTTP header, defined in W3C Baggage. The creation of that context, as well as the transformation of it into new HTTP headers, set by heimdall while communicating with further services is named propagation and the components responsible for the creation of such context object are named propagators.\nSince not every service in a multi-service system may set or understand the above OTEL specific HTTP headers (as these might still be using tracing vendor specific headers), interoperability can be achieved by configuring the required propagators by making use of the OTEL_PROPAGATORS environment variable. OTEL defines the following values for this variable:\ntracecontext - W3C Trace Context propagator. Enabled by default, if OTEL_PROPAGATORS is not set.\nbaggage - W3C Baggage propagator. Enabled by default if OTEL_PROPAGATORS is not set.\nb3 - Zipkin B3 Single Header propagator.\nb3multi - Zipkin B3 Multiple Header propagator.\njaeger - Jaeger Header propagator.\nxray - AWS X-Ray Header propagator.\nottrace - OT Trace Header propagator.\nnone - No automatically configured propagator.\nAll of these are supported by heimdall. In addition, following propagators can be configured as well:\ndatadog - Datadog APM Trace Header propagator.[1]\nConfigured propagators are used for inbound, as well as for outbound traffic.\nSpan Exporters Span Exporter handle the delivery of spans to external receivers (collectors, or agents). This is the final component in the trace export pipeline and typically provided by the APM vendor, like Jaeger, Zipkin, Instana, etc. Since not every multi-service system may have an up to day telemetry receiver supporting protocols defined by OTEL, interoperability can be achieved by configuring the required exporters by making use of the OTEL_TRACES_EXPORTER environment variable. OTEL defines the following values for this variable[2]:\notlp - OTLP exporter. Enabled by default if OTEL_TRACES_EXPORTER is not set.\nzipkin - Zipkin exporter to export spans in Zipkin data model.\nnone - No automatically configured exporter for traces.\nAll of these are supported by heimdall. In addition, following exporters can be configured as well:\ninstana - Instana exporter to export spans in Instana data model.[3]\nExample Configuration The environment variables set below configure heimdall to use Jaeger propagator and to export the spans via OTLP over grpc to the collector available under https://collector:4317.\nOTEL_PROPAGATORS=jaeger OTEL_TRACES_EXPORTER=otlp OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://collector:4317 If your environment supports OpenTelemetry and usage of defaults is ok, most probably, the only required environment variable to be set might be the OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.\nMetrics Heimdall makes use of OpenTelemetry to emit metrics. Depending on the configuration, push or pull based metrics export is supported.\nConfiguration As with tracing, the entire configuration happens via environment variables as defined by OpenTelemetry Environment Variables and OpenTelemetry SDK Configuration specifications. The generated metrics can either be exported by pushing these to an OTEL collector (the default behavior). Alternatively, the available metrics can be pulled and are then exported in the (Prometheus style).\nMetrics are generated and exported by default. If this is not desired, you can explicitly disable this behavior within the metrics property of heimdall’s configuration by making use of the following property:\nenabled: boolean (optional)\nBy making use of this property, you can configure heimdall to enable or disable the metrics collection. Defaults to true (metrics exposure is enabled).\nExample 5. Disabling metrics. metrics: enabled: false Metric Exporters By default, metrics are pushed to the OTEL collector using the http/protobuf transport protocol. You can change that behavior by making use of either the OTEL_EXPORTER_OTLP_METRICS_PROTOCOL, or the OTEL_EXPORTER_OTLP_PROTOCOL environment variable.\nTo let heimdall know where to push the metrics to, either OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, or OTEL_EXPORTER_OTLP_ENDPOINT must be defined.\nTo let heimdall expose metrics over a pull based service (Prometheus style), the OTEL_METRICS_EXPORTER environment variable must be set to \u0026#34;prometheus\u0026#34;. In that case heimdall will expose the 127.0.0.1:9464/metrics endpoint which can be queried using the HTTP GET verb. You can change the host and port of that service by making use of the OTEL_EXPORTER_PROMETHEUS_HOST and OTEL_EXPORTER_PROMETHEUS_PORT environment variables.\nYou can also disable metrics export by setting the OTEL_METRICS_EXPORTER environment variable to none.\nAvailable Metrics System metrics according to OpenTelemetry Semantic Conventions for System Metrics.\nProcess and Go runtime metrics according to OpenTelemetry Semantic Conventions for OS Process Metrics.\nInformation about the handled requests on each active service, as well as information about requests in progress according to OpenTelemetry Semantic Conventions for HTTP Metrics and General RPC conventions.\nInformation about the metrics endpoint itself (if enabled), including the number of internal errors encountered while gathering the metrics, number of current inflight and overall scrapes done.\nInformation about expiry for configured certificates.\nAll, but custom metrics adhere to the OpenTelementry semantic conventions. For that reason, only the custom metrics are listed in the table below.\nMetric: certificate.expiry Number of seconds until a certificate used by a particular service (main, management), or mechanism (e.g. jwt finalizer) expires. The metric type is UpDownCounter und the unit is s.\nAttribute Type Description service\nstring\nThe service, the certificate is configured for.\nissuer\nstring\nIssuer DN of the certificate.\nserial_nr\nstring\nThe serial number of the certificate.\nsubject\nstring\nSubject DN of the certificate.\ndns_names\nstring\nDNS entries in the SAN extension\nRuntime Profiling If enabled, heimdall exposes a /debug/pprof HTTP endpoint on port 10251 (See also the configuration options below) on which runtime profiling data in the profile.proto format (also known as pprof format) can be consumed by APM tools, like Google’s pprof, Grafana Phlare, Pyroscope and many more for visualization purposes. Following information is available:\nallocs - A sampling of all past memory allocations.\nblock - Stack traces that led to blocking on synchronization primitives.\ncmdline - The command line invocation of the current program, with arguments separated by NUL bytes.\ngoroutine - Stack traces of all current goroutines.\nheap - A sampling of memory allocations of live objects.\nmutex - Stack traces of holders of contended mutexes.\nprofile - Cpu profile. Profiling lasts for duration specified in seconds parameter, or for 30 seconds if not specified\nsymbol - Looks up the program counters listed in the request, responding with a table mapping program counters to function names.\nthreadcreate - Stack traces that led to the creation of new OS threads.\ntrace - Execution trace in binary form. Tracing lasts for duration specified in seconds parameter, or for 1 second if not specified.\nSee also the API documentation for the documentation of the actual API.\nConfiguration Configuration for this service can be adjusted in the profiling property of heimdall’s configuration by making use of the following properties.\nenabled: boolean (optional)\nBy making use of this property, you can configure heimdall to enable or disable runtime profiling. Defaults to false (profiling disabled).\nExample 6. Enabling profiling. profiling: enabled: true host: string (optional)\nBy making use of this property, you can specify the TCP/IP address on which heimdall should listen for connections from client applications interested in profiling data. The entry 0.0.0.0 allows listening for all IPv4 addresses. Defaults to 127.0.0.1, which allow only local TCP/IP “loopback” connections to be made.\nIf you operate heimdall in a container, you should set this property to a value, which would allow your APM system to scrape this information. Example 7. Configure heimdall to listen on 192.168.2.10. profiling: host: 192.168.2.10 port: integer (optional)\nBy making use of this property, you can specify the TCP port the heimdall should listen on. Defaults to 10251.\nExample 8. Configure heimdall to listen on port 9999 for runtime profiling requests. profiling: port: 9999 1. Datadog supports the OTLP protokoll. For that reason, there is no exporter available. 2. jaeger exporter has been marked as deprecated and is not supported anymore 3. Instana supports the W3C header used by OTEL. For that reason, there is no propagator available. ","description":"To support easier operation and integration in diverse APM products heimdall implements different observability mechanisms. The following sections provide insights about what can be expected.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_logging\"\u003eLogging\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall’s implementation uses \u003ca href=\"https://github.com/rs/zerolog\"\u003ezerolog\u003c/a\u003e - Zero Allocation JSON Logger, which can however also log in plain text. All emitted log statements include information related to distributed tracing (if tracing is enabled) so that not only log statements can be correlated to traces, but also all log statements belonging to single request/transaction can be correlated as well.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eLogging configuration can be adjusted in the \u003ccode\u003elog\u003c/code\u003e property of heimdall’s configuration and supports following properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eformat\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith \u003ccode\u003etext\u003c/code\u003e and \u003ccode\u003egelf\u003c/code\u003e being the available formats. \u003ccode\u003etext\u003c/code\u003e is the default format. And \u003ccode\u003egelf\u003c/code\u003e defines a JSON format adhering to \u003ca href=\"https://docs.graylog.org/v1/docs/gelf\"\u003eGELF\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsage of \u003ccode\u003etext\u003c/code\u003e (default) format is not recommended for production deployments as it requires more computational resources and is hence slow.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Configuring logging to emit logs using GELD format.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eformat\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egelf\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003elevel\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing log levels are available: \u003ccode\u003etrace\u003c/code\u003e, \u003ccode\u003edebug\u003c/code\u003e, \u003ccode\u003einfo\u003c/code\u003e, \u003ccode\u003ewarn\u003c/code\u003e, \u003ccode\u003eerror\u003c/code\u003e, \u003ccode\u003efatal\u003c/code\u003e, \u003ccode\u003epanic\u003c/code\u003e and \u003ccode\u003edisabled\u003c/code\u003e. The last one effectively disables logging. You usually do not want to do this. By default, the level is set to \u003ccode\u003eerror\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003ccode\u003edebug\u003c/code\u003e and \u003ccode\u003etrace\u003c/code\u003e log levels are not meant for production as setting log level to one of these will result in a high log verbosity and also affect performance pretty much. Both are only meant for setup analysis and debugging! \u003ccode\u003etrace\u003c/code\u003e log level will also dump all incoming and outgoing HTTP requests and responses, as well as the contents of objects used in templates. That dump is unedited. That means sensitive data will be available in logs.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nDue to some limitations of the GRPC framework capabilities, setting log level to \u003ccode\u003etrace\u003c/code\u003e will not dump GRPC requests and responses. If you need these for analysis purposes (e.g. when debugging the integration with envoy proxy), you’ll have to set \u003ca href=\"https://pkg.go.dev/net/http?utm_source=godoc#hdr-HTTP_2\"\u003e\u003ccode\u003eGODEBUG\u003c/code\u003e\u003c/a\u003e as well as the \u003ca href=\"https://pkg.go.dev/google.golang.org/grpc/examples/features/debugging#section-readme\"\u003e\u003ccode\u003eGRPC_GO_LOG_VERBOSITY_LEVEL\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"https://pkg.go.dev/google.golang.org/grpc/examples/features/debugging#section-readme\"\u003e\u003ccode\u003eGRPC_GO_LOG_SEVERITY_LEVEL\u003c/code\u003e\u003c/a\u003e environment variables.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Configuring logging to emit logs in debug level.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edebug\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_regular_log_events\"\u003eRegular Log Events\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you configure heimdall to log in \u003ccode\u003etext\u003c/code\u003e format, you can expect output similar to the one shown below:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"log\"\u003e2022-08-03T12:51:48+02:00 INF Opentelemetry tracing initialized.\n2022-08-03T12:51:48+02:00 INF Instantiating in memory cache\n2022-08-03T12:51:48+02:00 DBG Creating rule set event queue.\n2022-08-03T12:51:48+02:00 INF Loading pipeline definitions\n2022-08-03T12:51:48+02:00 DBG Loading definitions for authenticators\n2022-08-03T12:51:48+02:00 DBG Loading pipeline definition id=anonymous_authenticator type=anonymous\n...\n2022-08-03T12:51:52+02:00 DBG Decision endpoint called\n2022-08-03T12:51:52+02:00 DBG Executing default rule\n2022-08-03T12:51:52+02:00 DBG Authenticating using anonymous authenticator\n2022-08-03T12:51:52+02:00 DBG Finalizing using JWT finalizer\n2022-08-03T12:51:52+02:00 DBG Generating new JWT\n2022-08-03T12:51:52+02:00 DBG Finalizing request\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsage of this format is not recommended for production deployments as it requires more computational resources and is hence slow.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOtherwise, if you configure it to use \u003ccode\u003egelf\u003c/code\u003e (see \u003ca href=\"https://docs.graylog.org/v1/docs/gelf\"\u003eGELF\u003c/a\u003e for format details) format, the output will look as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;INFO\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Opentracing tracer initialized.\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;INFO\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Instantiating in memory cache\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Creating rule set event queue.\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;INFO\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Loading pipeline definitions\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Loading definitions for authenticators\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;anonymous_authenticator\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;type\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;anonymous\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Loading pipeline definition\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\n\u003c/span\u003e\u003cspan class=\"err\"\u003e...\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Decision endpoint called\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Executing default rule\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Authenticating using anonymous authenticator\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Finalizing using JWT finalizer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Generating new JWT\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Finalizing request\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach log statement does also include the following fields in both log formats for incoming requests if tracing is enabled:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_trace_id\u003c/code\u003e - The trace id as defined by OpenTelemetry.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_span_id\u003c/code\u003e - The span id as defined by OpenTelemetry of the current transaction.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_parent_id\u003c/code\u003e - The span id of the callee, which started the given transaction. Only present if the callee set the corresponding tracing header.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_access_log_events\"\u003eAccess Log Events\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition to regular logs, heimdall emits access logs. These events are always emitted regardless the configured log level and the log level of these events in the log output is always \u003ccode\u003eINFO\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach request to any of heimdall’s endpoints will result in two access events:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eevent describing the start of the transaction, and an\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eevent describing the finalization of the transaction.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing are the fields, which are always set for both events:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_tx_start\u003c/code\u003e - Timestamp in Unix epoch format, when the transaction started.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_client_ip\u003c/code\u003e - The IP of the client of the request.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the event has been emitted for an HTTP request, following fields are set as well:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_method\u003c/code\u003e - The HTTP method used by the client while calling heimdall’s endpoint.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_path\u003c/code\u003e - The used HTTP path.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_user_agent\u003c/code\u003e - The agent used by the client. The value is taken from the HTTP \u0026#34;User-Agent\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_host\u003c/code\u003e - The host part of the URI, the client is using while communicating with Heimdall.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_scheme\u003c/code\u003e - The scheme part of the URI, the client is using while communicating with Heimdall.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the event has been emitted for a GRPC request, following fields are set:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_grpc_method\u003c/code\u003e - The full GRPC method used.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the request comes from an intermediary, like e.g. an API Gateway and heimdall is configured to trust that \u0026#34;proxy\u0026#34; (see \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003e\u003ccode\u003etrusted_proxies\u003c/code\u003e configuration\u003c/a\u003e), then following fields will be part of the events as well if the corresponding HTTP headers were sent.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_x_forwarded_proto\u003c/code\u003e - The value of the \u0026#34;X-Forwarded-Proto\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_x_forwarded_host\u003c/code\u003e - The value of the \u0026#34;X-Forwarded-Host\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_x_forwarded_uri\u003c/code\u003e - The value of the \u0026#34;X-Forwarded-Uri\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_x_forwarded_for\u003c/code\u003e - The value of the \u0026#34;X-Forwarded-For\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_forwarded\u003c/code\u003e - The value of the \u0026#34;Forwarded\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing are the fields, which are set in the transaction finalization event in addition:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_body_bytes_sent\u003c/code\u003e - The length of the response body.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_tx_duration_ms\u003c/code\u003e - The duration of the transaction in milliseconds. If heimdall is operated in proxy mode, it will also include the time used to communicate with the upstream service.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_access_granted\u003c/code\u003e - Set either to \u003ccode\u003etrue\u003c/code\u003e or \u003ccode\u003efalse\u003c/code\u003e, indicating whether heimdall granted access or not.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_subject\u003c/code\u003e - The subject identifier if the access was granted.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_error\u003c/code\u003e - The information about an error, which e.g. led to the denial of the request.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the finalization event has been emitted for an HTTP request, following fields are set as well:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_status_code\u003c/code\u003e - The numeric HTTP response status code\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the finalization event has been emitted for a GRPC request, following fields are set:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_grpc_status_code\u003c/code\u003e - The numeric GRPC status code.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing are the fields, which are set if tracing is enabled:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_trace_id\u003c/code\u003e - The trace id as defined by OpenTelemetry.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_span_id\u003c/code\u003e - The span id as defined by OpenTelemetry of the current transaction.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_parent_id\u003c/code\u003e - The span id of the callee, which started the given transaction. Only present if the callee set the corresponding tracing header.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you configure heimdall to log in \u003ccode\u003etext\u003c/code\u003e format, you can expect output as shown below:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003e2022-08-03T12:40:16+02:00 INF TX started _client_ip=127.0.0.1 _http_host=127.0.0.1:4468 _http_method=GET\n _http_path=/foo _http_scheme=http _http_user_agent=curl/7.74.0 _parent_id=3449bda63ed70206\n _span_id=f57c007257fee0ed _trace_id=00000000000000000a5af97bffe6a8a2 _tx_start=1659523216\n\n....\n\n2022-08-03T12:40:16+02:00 INF TX finished _access_granted=true _body_bytes_sent=0 _client_ip=127.0.0.1\n _http_host=127.0.0.1:4468 _http_method=GET _http_path=/foo _http_scheme=http _http_status_code=202\n _http_user_agent=curl/7.74.0 _subject=anonymous _parent_id=3449bda63ed70206 _span_id=f57c007257fee0ed\n _trace_id=00000000000000000a5af97bffe6a8a2 _tx_duration_ms=0 _tx_start=1659523216\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOtherwise, if you configure it to use \u003ccode\u003egelf\u003c/code\u003e format, the output will look as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;INFO\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_tx_start\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_client_ip\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;127.0.0.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_method\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;GET\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_path\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;/foo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_user_agent\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;curl/7.74.0\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;127.0.0.1:4468\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_scheme\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;http\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;TX started\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\n\u003c/span\u003e\u003cspan class=\"err\"\u003e....\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;INFO\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_tx_start\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_client_ip\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;127.0.0.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_method\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;GET\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_path\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;/foo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_user_agent\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;curl/7.74.0\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;127.0.0.1:4468\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_scheme\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;http\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_body_bytes_sent\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_status_code\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e200\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_tx_duration_ms\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_subject\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;anonymous\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_access_granted\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;TX finished\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_tracing\"\u003eTracing\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall makes use of \u003ca href=\"https://opentelemetry.io/\"\u003eOpenTelemetry\u003c/a\u003e for distributed tracing to support recording of paths taken by requests and supports all environment variables including the defined values according to \u003ca href=\"https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/\"\u003eOpenTelemetry Environment Variables\u003c/a\u003e and \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/\"\u003eOpenTelemetry SDK Configuration\u003c/a\u003e specifications. In addition to these environment variables, heimdall defines some additional options, which are described below and can be used to tune the behaviour.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_2\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy default, tracing is enabled and can be disabled or slightly tuned in the \u003ccode\u003etracing\u003c/code\u003e property of heimdall’s configuration supporting the following properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eenabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can configure heimdall to enable or disable tracing. Defaults to \u003ccode\u003etrue\u003c/code\u003e (tracing enabled).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Disabling tracing.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003espan_processor\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith \u003ccode\u003esimple\u003c/code\u003e and \u003ccode\u003ebatch\u003c/code\u003e being the available options. By setting this property, you can define how heimdall shall process the created spans. Defaults to \u003ccode\u003ebatch\u003c/code\u003e. This property is only there, as there is no corresponding setting option via OTEL tracing environment variables available.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Setting the span processor to export completed spans in batches.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003espan_processor\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebatch\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDescription of the options:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003esimple\u003c/code\u003e - Configures heimdall to synchronously export the created spans via configured exporters. This is not recommended for production use as it is slow and has a high computation resource usage overhead. It might be however good for testing, debugging, or showing examples of other features.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ebatch\u003c/code\u003e - Configures heimdall to send completed span batches to the exporter. Recommended setting for production use.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_tracing_context_propagation\"\u003eTracing Context Propagation\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhen a request arrives at heimdall, it will create a trace context object based on the received headers, which according to OTEL are the \u003ccode\u003etraceparent\u003c/code\u003e and \u003ccode\u003etracestate\u003c/code\u003e HTTP headers, defined in \u003ca href=\"https://www.w3.org/TR/trace-context/\"\u003eW3C Trace Context\u003c/a\u003e as well as \u003ccode\u003ebaggage\u003c/code\u003e HTTP header, defined in \u003ca href=\"https://www.w3.org/TR/baggage/\"\u003eW3C Baggage\u003c/a\u003e. The creation of that context, as well as the transformation of it into new HTTP headers, set by heimdall while communicating with further services is named propagation and the components responsible for the creation of such context object are named propagators.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince not every service in a multi-service system may set or understand the above OTEL specific HTTP headers (as these might still be using tracing vendor specific headers), interoperability can be achieved by configuring the required propagators by making use of the \u003ccode\u003eOTEL_PROPAGATORS\u003c/code\u003e environment variable. OTEL defines the following values for this variable:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etracecontext\u003c/code\u003e - \u003ca href=\"https://www.w3.org/TR/trace-context/\"\u003eW3C Trace Context\u003c/a\u003e propagator. Enabled by default, if \u003ccode\u003eOTEL_PROPAGATORS\u003c/code\u003e is not set.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ebaggage\u003c/code\u003e - \u003ca href=\"https://www.w3.org/TR/baggage/\"\u003eW3C Baggage\u003c/a\u003e propagator. Enabled by default if \u003ccode\u003eOTEL_PROPAGATORS\u003c/code\u003e is not set.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eb3\u003c/code\u003e - \u003ca href=\"https://github.com/openzipkin/b3-propagation#single-header\"\u003eZipkin B3 Single Header\u003c/a\u003e propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eb3multi\u003c/code\u003e - \u003ca href=\"https://github.com/openzipkin/b3-propagation#multiple-headers\"\u003eZipkin B3 Multiple Header\u003c/a\u003e propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ejaeger\u003c/code\u003e - \u003ca href=\"https://www.jaegertracing.io/docs/1.38/client-libraries/#propagation-format\"\u003eJaeger Header\u003c/a\u003e propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003exray\u003c/code\u003e - \u003ca href=\"https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader\"\u003eAWS X-Ray Header\u003c/a\u003e propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eottrace\u003c/code\u003e - \u003ca href=\"https://github.com/opentracing?q=basic\u0026amp;type=\u0026amp;language=\"\u003eOT Trace Header\u003c/a\u003e propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003enone\u003c/code\u003e - No automatically configured propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll of these are supported by heimdall. In addition, following propagators can be configured as well:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003edatadog\u003c/code\u003e - \u003ca href=\"https://www.datadoghq.com/product/apm/\"\u003eDatadog APM Trace Header\u003c/a\u003e propagator.\u003csup class=\"footnote\"\u003e[\u003ca id=\"_footnoteref_1\" class=\"footnote\" href=\"#_footnotedef_1\" title=\"View footnote.\"\u003e1\u003c/a\u003e]\u003c/sup\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfigured propagators are used for inbound, as well as for outbound traffic.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_span_exporters\"\u003eSpan Exporters\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpan Exporter handle the delivery of spans to external receivers (collectors, or agents). This is the final component in the trace export pipeline and typically provided by the APM vendor, like Jaeger, Zipkin, Instana, etc. Since not every multi-service system may have an up to day telemetry receiver supporting protocols defined by OTEL, interoperability can be achieved by configuring the required exporters by making use of the \u003ccode\u003eOTEL_TRACES_EXPORTER\u003c/code\u003e environment variable. OTEL defines the following values for this variable\u003csup class=\"footnote\"\u003e[\u003ca id=\"_footnoteref_2\" class=\"footnote\" href=\"#_footnotedef_2\" title=\"View footnote.\"\u003e2\u003c/a\u003e]\u003c/sup\u003e:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eotlp\u003c/code\u003e - \u003ca href=\"https://opentelemetry.io/docs/reference/specification/protocol/otlp/\"\u003eOTLP\u003c/a\u003e exporter. Enabled by default if \u003ccode\u003eOTEL_TRACES_EXPORTER\u003c/code\u003e is not set.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ezipkin\u003c/code\u003e - \u003ca href=\"https://zipkin.io/zipkin-api/\"\u003eZipkin\u003c/a\u003e exporter to export spans in Zipkin data model.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003enone\u003c/code\u003e - No automatically configured exporter for traces.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll of these are supported by heimdall. In addition, following exporters can be configured as well:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003einstana\u003c/code\u003e - \u003ca href=\"https://www.instana.com/\"\u003eInstana\u003c/a\u003e exporter to export spans in Instana data model.\u003csup class=\"footnote\"\u003e[\u003ca id=\"_footnoteref_3\" class=\"footnote\" href=\"#_footnotedef_3\" title=\"View footnote.\"\u003e3\u003c/a\u003e]\u003c/sup\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_example_configuration\"\u003eExample Configuration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe environment variables set below configure heimdall to use Jaeger propagator and to export the spans via OTLP over grpc to the collector available under \u003ccode\u003ehttps://collector:4317\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003eOTEL_PROPAGATORS=jaeger\nOTEL_TRACES_EXPORTER=otlp\nOTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc\nOTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://collector:4317\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf your environment supports OpenTelemetry and usage of defaults is ok, most probably, the only required environment variable to be set might be the \u003ccode\u003eOTEL_EXPORTER_OTLP_TRACES_ENDPOINT\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_metrics\"\u003eMetrics\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall makes use of \u003ca href=\"https://opentelemetry.io/\"\u003eOpenTelemetry\u003c/a\u003e to emit metrics. Depending on the configuration, push or pull based metrics export is supported.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_3\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with tracing, the entire configuration happens via environment variables as defined by \u003ca href=\"https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/\"\u003eOpenTelemetry Environment Variables\u003c/a\u003e and \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/\"\u003eOpenTelemetry SDK Configuration\u003c/a\u003e specifications. The generated metrics can either be exported by pushing these to an OTEL collector (the default behavior). Alternatively, the available metrics can be pulled and are then exported in the (\u003ca href=\"https://grafana.com/oss/prometheus/\"\u003ePrometheus\u003c/a\u003e style).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eMetrics are generated and exported by default. If this is not desired, you can explicitly disable this behavior within the \u003ccode\u003emetrics\u003c/code\u003e property of heimdall’s configuration by making use of the following property:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eenabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can configure heimdall to enable or disable the metrics collection. Defaults to \u003ccode\u003etrue\u003c/code\u003e (metrics exposure is enabled).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Disabling metrics.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emetrics\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_metric_exporters\"\u003eMetric Exporters\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy default, metrics are pushed to the OTEL collector using the \u003ccode\u003ehttp/protobuf\u003c/code\u003e transport protocol. You can change that behavior by making use of either the \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_metrics_protocol\"\u003e\u003ccode\u003eOTEL_EXPORTER_OTLP_METRICS_PROTOCOL\u003c/code\u003e\u003c/a\u003e, or the \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_protocol\"\u003e\u003ccode\u003eOTEL_EXPORTER_OTLP_PROTOCOL\u003c/code\u003e\u003c/a\u003e environment variable.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo let heimdall know where to push the metrics to, either \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_metrics_endpoint\"\u003e\u003ccode\u003eOTEL_EXPORTER_OTLP_METRICS_ENDPOINT\u003c/code\u003e\u003c/a\u003e, or \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_endpoint\"\u003e\u003ccode\u003eOTEL_EXPORTER_OTLP_ENDPOINT\u003c/code\u003e\u003c/a\u003e must be defined.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo let heimdall expose metrics over a pull based service (\u003ca href=\"https://grafana.com/oss/prometheus/\"\u003ePrometheus\u003c/a\u003e style), the \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_metrics_exporter\"\u003e\u003ccode\u003eOTEL_METRICS_EXPORTER\u003c/code\u003e\u003c/a\u003e environment variable must be set to \u003ccode\u003e\u0026#34;prometheus\u0026#34;\u003c/code\u003e. In that case heimdall will expose the \u003ccode\u003e127.0.0.1:9464/metrics\u003c/code\u003e endpoint which can be queried using the HTTP GET verb. You can change the host and port of that service by making use of the \u003ca href=\"https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#prometheus-exporter\"\u003e\u003ccode\u003eOTEL_EXPORTER_PROMETHEUS_HOST\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#prometheus-exporter\"\u003e\u003ccode\u003eOTEL_EXPORTER_PROMETHEUS_PORT\u003c/code\u003e\u003c/a\u003e environment variables.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can also disable metrics export by setting the \u003ccode\u003eOTEL_METRICS_EXPORTER\u003c/code\u003e environment variable to \u003ccode\u003enone\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_available_metrics\"\u003eAvailable Metrics\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eSystem metrics according to \u003ca href=\"https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/system-metrics/\"\u003eOpenTelemetry Semantic Conventions for System Metrics\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eProcess and Go runtime metrics according to \u003ca href=\"https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/process-metrics/\"\u003eOpenTelemetry Semantic Conventions for OS Process Metrics\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eInformation about the handled requests on each active service, as well as information about requests in progress according to OpenTelemetry \u003ca href=\"https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/http-metrics/\"\u003eSemantic Conventions for HTTP Metrics\u003c/a\u003e and \u003ca href=\"https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/rpc-metrics/\"\u003eGeneral RPC conventions\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eInformation about the metrics endpoint itself (if enabled), including the number of internal errors encountered while gathering the metrics, number of current inflight and overall scrapes done.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eInformation about expiry for configured certificates.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll, but custom metrics adhere to the \u003ca href=\"https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/\"\u003eOpenTelementry semantic conventions\u003c/a\u003e. For that reason, only the custom metrics are listed in the table below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_metric_certificate_expiry\"\u003eMetric: \u003ccode\u003ecertificate.expiry\u003c/code\u003e\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNumber of seconds until a certificate used by a particular service (main, management), or mechanism (e.g. jwt finalizer) expires. The metric type is UpDownCounter und the unit is s.\u003c/p\u003e\n\u003c/div\u003e\n\u003ctable class=\"tableblock frame-all grid-all stretch\"\u003e\n\u003ccolgroup\u003e\n\u003ccol style=\"width: 25%;\"/\u003e\n\u003ccol style=\"width: 12.5%;\"/\u003e\n\u003ccol style=\"width: 62.5%;\"/\u003e\n\u003c/colgroup\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eAttribute\u003c/strong\u003e\u003c/th\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eType\u003c/strong\u003e\u003c/th\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eDescription\u003c/strong\u003e\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ccode\u003eservice\u003c/code\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003estring\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eThe service, the certificate is configured for.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ccode\u003eissuer\u003c/code\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003estring\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eIssuer DN of the certificate.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ccode\u003eserial_nr\u003c/code\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003estring\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eThe serial number of the certificate.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ccode\u003esubject\u003c/code\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003estring\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eSubject DN of the certificate.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ccode\u003edns_names\u003c/code\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003estring\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eDNS entries in the SAN extension\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_runtime_profiling\"\u003eRuntime Profiling\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf enabled, heimdall exposes a \u003ccode\u003e/debug/pprof\u003c/code\u003e HTTP endpoint on port \u003ccode\u003e10251\u003c/code\u003e (See also the configuration options below) on which runtime profiling data in the \u003ccode\u003eprofile.proto\u003c/code\u003e format (also known as \u003ccode\u003epprof\u003c/code\u003e format) can be consumed by APM tools, like \u003ca href=\"https://github.com/google/pprof\"\u003eGoogle’s pprof\u003c/a\u003e, \u003ca href=\"https://grafana.com/oss/phlare/\"\u003eGrafana Phlare\u003c/a\u003e, \u003ca href=\"https://pyroscope.io/\"\u003ePyroscope\u003c/a\u003e and many more for visualization purposes. Following information is available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eallocs\u003c/code\u003e - A sampling of all past memory allocations.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eblock\u003c/code\u003e - Stack traces that led to blocking on synchronization primitives.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ecmdline\u003c/code\u003e - The command line invocation of the current program, with arguments separated by NUL bytes.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003egoroutine\u003c/code\u003e - Stack traces of all current goroutines.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eheap\u003c/code\u003e - A sampling of memory allocations of live objects.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emutex\u003c/code\u003e - Stack traces of holders of contended mutexes.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eprofile\u003c/code\u003e - Cpu profile. Profiling lasts for duration specified in \u003ccode\u003eseconds\u003c/code\u003e parameter, or for 30 seconds if not specified\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003esymbol\u003c/code\u003e - Looks up the program counters listed in the request, responding with a table mapping program counters to function names.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ethreadcreate\u003c/code\u003e - Stack traces that led to the creation of new OS threads.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etrace\u003c/code\u003e - Execution trace in binary form. Tracing lasts for duration specified in \u003ccode\u003eseconds\u003c/code\u003e parameter, or for 1 second if not specified.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSee also the \u003ca href=\"/openapi/#tag/Profiling\"\u003eAPI\u003c/a\u003e documentation for the documentation of the actual API.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_4\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration for this service can be adjusted in the \u003ccode\u003eprofiling\u003c/code\u003e property of heimdall’s configuration by making use of the following properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eenabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can configure heimdall to enable or disable runtime profiling. Defaults to \u003ccode\u003efalse\u003c/code\u003e (profiling disabled).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 6. Enabling profiling.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eprofiling\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehost\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can specify the TCP/IP address on which heimdall should listen for connections from client applications interested in profiling data. The entry \u003ccode\u003e0.0.0.0\u003c/code\u003e allows listening for all IPv4 addresses. Defaults to \u003ccode\u003e127.0.0.1\u003c/code\u003e, which allow only local TCP/IP “loopback” connections to be made.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you operate heimdall in a container, you should set this property to a value, which would allow your APM system to scrape this information.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 7. Configure heimdall to listen on \u003ccode\u003e192.168.2.10\u003c/code\u003e.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eprofiling\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e192.168.2.10\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eport\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can specify the TCP port the heimdall should listen on. Defaults to \u003ccode\u003e10251\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 8. Configure heimdall to listen on port \u003ccode\u003e9999\u003c/code\u003e for runtime profiling requests.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eprofiling\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e9999\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"footnotes\"\u003e\n\u003chr/\u003e\n\u003cdiv class=\"footnote\" id=\"_footnotedef_1\"\u003e\n\u003ca href=\"#_footnoteref_1\"\u003e1\u003c/a\u003e. Datadog supports the OTLP protokoll. For that reason, there is no exporter available.\n\u003c/div\u003e\n\u003cdiv class=\"footnote\" id=\"_footnotedef_2\"\u003e\n\u003ca href=\"#_footnoteref_2\"\u003e2\u003c/a\u003e. jaeger exporter has been marked as deprecated and is not supported anymore\n\u003c/div\u003e\n\u003cdiv class=\"footnote\" id=\"_footnotedef_3\"\u003e\n\u003ca href=\"#_footnoteref_3\"\u003e3\u003c/a\u003e. Instana supports the W3C header used by OTEL. For that reason, there is no propagator available.\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Operations"],"tags":null,"title":"Observability ","url":"/docs/operations/observability/"},{"categories":null,"content":" Even some default caching is in place, and you can instruct heimdall to cache particular data for some amount of time, like e.g how long to cache the response from the JWKS endpoint when using the JWT Authenticator, all these options require a caching backend to be available. Otherwise, the corresponding configurations do not have any effect.\nConfiguration of that backend happens by making use of the cache property in heimdall’s configuration, which supports the following options:\ntype - The mandatory specific type of the cache backend.\nconfig - A cache backend specific configuration if required by the type.\nNoop Backend With that backend configured, caching is disabled entirely. That means any cache settings on any mechanism do not have any effect. Even those, applied by heimdall by default are disabled.\nTo configure this backend, you have to specify noop as type. No further configuration is supported. Here an example:\ncache: type: noop In-Memory Backend This backend manages the cached items in memory of heimdall’s process.\nTo configure it, you have to specify in-memory as type. No further configuration is supported. Here an example:\ncache: type: in-memory By default, heimdall makes use of this backend. Redis Backends As the name of this chapter implies, there are multiple backend types, you can configure to make use of Redis as distributed cache:\na Redis single instance,\na Redis cluster and\na Redis sentinel.\nAll types use pipelining to increase performance and do also make use of client side caching if not disabled (see also below).\nCommon Settings All Redis cache backend types support the following configuration options:\ncredentials: Credentials (optional)\nHerewith you can define the credentials to be used for connection purposes. Following settings are possible\npath: string (mandatory)\nPath to a JSON/YAML file with credentials (supports watching for secrets rotation) specifying the username and password as shown below.\n# contents of a credentials file username: Aladdin password: SesameOpen! If used no other properties can be configured for credentials.\nusername: string(optional)\nThe username to use to connect to the Redis DB/Cluster, and\npassword: string(mandatory)\nThe password to be used\nclient_cache: ClientCache (optional)\nConfigurs the client cache to reduce roundtrip time. Following settings are possible:\ndisabled: boolean (optional)\nWhether the client cache should be disabled. Defaults to false.\nttl: Duration (optional)\nSpecifies the maximum TTL on the client side for all used keys. If the key’s TTL on the server is smaller than the client side TTL, the client side TTL will be capped.\nsize_per_connection: ByteSize (optional)\nClient side cache size that bind to each TCP connection to a single redis instance. Defaults to 128MB.\nbuffer_limit: BufferLimit (optional)\nRead and write buffer limits for established connections. Following configuration properties are supported:\nread: ByteSize (optional)\nThe maximum size for the read buffer allowed to read the full request including body. Defaults to 0.5MB.\nwrite: ByteSize (optional)\nThe maximum size for the write buffer of the response. Defaults to 0.5MB.\ntimeout: Timeout (optional)\nBy using this property you can override the default connection timeouts. Following properties are supported:\nwrite: Duration (optional)\nThe maximum duration before timing out writes of the response. Defaults to 150s.\nmax_flush_delay: Duration (optional)\nData flush delay. When greater than zero, pauses pipeline write loop for some time (not larger than the specified delay) after each flushing of data to the connection. This gives pipeline a chance to collect more commands to send to Redis. Adding this delay increases latency, reduces throughput, but in most cases may significantly reduce application and Redis CPU utilization due to less executed system calls. By default, the data is flushed to the connection without extra delays. Depending on network latency and application-specific conditions the value of max_flush_delay may vary, something like 20 µs should not affect latency/throughput a lot but still produce notable CPU usage reduction under load. Defaults to 0s.\ntls: TLS (optional)\nTLS settings. By default, the communication to Redis happens over TLS. This requires however a properly configured trust store, as otherwise heimdall won’t trust the certificates used by the Redis services. In addition to the referenced configuration options, you can also make use of the following properties:\ndisabled: boolean (optional)\nDisables TLS. Defaults to false.\nThis property can be set to true only if heimdall is started with the --insecure-skip-egress-tls-enforcement flag, which allows insecure communication with any configured service. Redis Single Instance As the name implies, this type supports configuration of a single instance Redis DB.\nTo use it, you have to specify redis as type. Configuration is mandatory with following options in addition to the configuration options described in Common Settings.\naddress: string (mandatory)\nThe Redis instance address to connect to.\ndb: integer (optional)\nRedis DB ID to use. Defaults to 0.\nHere an example:\ncache: type: redis config: address: foo:12345 credentials: path: /path/to/credentials.yaml client_cache: ttl: 10m size_per_connection: 128MB buffer_limit: read: 1MB write: 1MB timeout: write: 150s max_flush_delay: 20us tls: # TLS client auth is used here key_store: path: /path/to/keystore/file.pem password: ${MY_REDIS_CLIENT_KEYSTORE} min_version: TLS1.2 Redis Cluster As the name implies, this type supports configuration of a Redis cluster.\nTo use it, you have to specify redis-cluster as type. Configuration is mandatory with following options in addition to the configuration options described in Common Settings.\nnodes: array of strings (mandatory)\nThe addresses of Redis nodes to connect to.\nHere an example:\ncache: type: redis-cluster config: nodes: - foo:1234 - bar:1234 credentials: username: ${MY_REDIS_USER} password: ${MY_REDIS_PASSWORD} Redis Sentinel As the name implies, this type supports configuration of a Redis sentinel.\nTo use it, you have to specify redis-sentinel as type. Configuration is mandatory with following options in addition to the configuration options described in Common Settings.\nnodes: array of strings (mandatory)\nThe addresses of Redis sentinel nodes to connect to.\ndb: integer (optional)\nRedis DB ID to use. Defaults to 0.\nmaster: string (mandatory)\nSentinel master set name\nSame credentials are used to connect to the sentinel service and to the Redis DB instances. This is also true if TLS client authentication is used. Here an example:\ncache: type: redis-sentinel config: nodes: - foo:1234 - bar:1234 db: 0 master: whatever credentials: path: /path/to/credentials.yaml ","description":"To increase performance, you can configure heimdall to make use of caching. Indeed, caching is even done by default in some places.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEven some default caching is in place, and you can instruct heimdall to cache particular data for some amount of time, like e.g how long to cache the response from the JWKS endpoint when using the \u003ca href=\"/docs/mechanisms/authenticators/#_jwt\"\u003eJWT Authenticator\u003c/a\u003e, all these options require a caching backend to be available. Otherwise, the corresponding configurations do not have any effect.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration of that backend happens by making use of the \u003ccode\u003ecache\u003c/code\u003e property in heimdall’s configuration, which supports the following options:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e - The mandatory specific type of the cache backend.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003econfig\u003c/code\u003e - A cache backend specific configuration if required by the type.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_noop_backend\"\u003eNoop Backend\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith that backend configured, caching is disabled entirely. That means any cache settings on any mechanism do not have any effect. Even those, applied by heimdall by default are disabled.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo configure this backend, you have to specify \u003ccode\u003enoop\u003c/code\u003e as type. No further configuration is supported. Here an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_in_memory_backend\"\u003eIn-Memory Backend\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis backend manages the cached items in memory of heimdall’s process.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo configure it, you have to specify \u003ccode\u003ein-memory\u003c/code\u003e as type. No further configuration is supported. Here an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ein-memory\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nBy default, heimdall makes use of this backend.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_redis_backends\"\u003eRedis Backends\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name of this chapter implies, there are multiple backend types, you can configure to make use of \u003ca href=\"https://redis.io/\"\u003eRedis\u003c/a\u003e as distributed cache:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ea \u003ca href=\"#_redis_single_instance\"\u003eRedis single instance\u003c/a\u003e,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea \u003ca href=\"#_redis_cluster\"\u003eRedis cluster\u003c/a\u003e and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea \u003ca href=\"#_redis_sentinel\"\u003eRedis sentinel\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll types use pipelining to increase performance and do also make use of client side caching if not disabled (see also below).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_common_settings\"\u003eCommon Settings\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll Redis cache backend types support the following configuration options:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecredentials\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eCredentials\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHerewith you can define the credentials to be used for connection purposes. Following settings are possible\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epath\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePath to a JSON/YAML file with credentials (supports watching for secrets rotation) specifying the \u003ccode\u003eusername\u003c/code\u003e and \u003ccode\u003epassword\u003c/code\u003e as shown below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# contents of a credentials file\u003c/span\u003e\n\u003cspan class=\"na\"\u003eusername\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAladdin\u003c/span\u003e\n\u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSesameOpen!\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf used no other properties can be configured for credentials.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eusername\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e(optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe username to use to connect to the Redis DB/Cluster, and\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epassword\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e(mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe password to be used\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclient_cache\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eClientCache\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfigurs the client cache to reduce roundtrip time. Following settings are possible:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edisabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhether the client cache should be disabled. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ettl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies the maximum TTL on the client side for all used keys. If the key’s TTL on the server is smaller than the client side TTL, the client side TTL will be capped.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esize_per_connection\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eClient side cache size that bind to each TCP connection to a single redis instance. Defaults to 128MB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebuffer_limit\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eBufferLimit\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRead and write buffer limits for established connections. Following configuration properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eread\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size for the read buffer allowed to read the full request including body. Defaults to 0.5MB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size for the write buffer of the response. Defaults to 0.5MB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etimeout\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eTimeout\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy using this property you can override the default connection timeouts. Following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum duration before timing out writes of the response. Defaults to 150s.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_flush_delay\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eData flush delay. When greater than zero, pauses pipeline write loop for some time (not larger than the specified delay) after each flushing of data to the connection. This gives pipeline a chance to collect more commands to send to Redis. Adding this delay increases latency, reduces throughput, but in most cases may significantly reduce application and Redis CPU utilization due to less executed system calls. By default, the data is flushed to the connection without extra delays. Depending on network latency and application-specific conditions the value of max_flush_delay may vary, something like 20 µs should not affect latency/throughput a lot but still produce notable CPU usage reduction under load. Defaults to 0s.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etls\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_tls\"\u003eTLS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTLS settings. By default, the communication to Redis happens over TLS. This requires however a properly configured \u003ca href=\"/docs/operations/security/#_tls_trust_store\"\u003etrust store\u003c/a\u003e, as otherwise heimdall won’t trust the certificates used by the Redis services. In addition to the referenced configuration options, you can also make use of the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edisabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDisables TLS. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis property can be set to \u003ccode\u003etrue\u003c/code\u003e only if heimdall is started with the \u003ccode\u003e--insecure-skip-egress-tls-enforcement\u003c/code\u003e flag, which allows insecure communication with any configured service.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_redis_single_instance\"\u003eRedis Single Instance\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this type supports configuration of a single instance Redis DB.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo use it, you have to specify \u003ccode\u003eredis\u003c/code\u003e as type. Configuration is mandatory with following options in addition to the configuration options described in \u003ca href=\"#_common_settings\"\u003eCommon Settings\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eaddress\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe Redis instance address to connect to.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edb\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRedis DB ID to use. Defaults to 0.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredis\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo:12345\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecredentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/credentials.yaml\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10m\u003c/span\u003e\n \u003cspan class=\"na\"\u003esize_per_connection\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e128MB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuffer_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1MB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1MB\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e150s\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_flush_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e20us\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# TLS client auth is used here\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/keystore/file.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${MY_REDIS_CLIENT_KEYSTORE}\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_redis_cluster\"\u003eRedis Cluster\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this type supports configuration of a Redis cluster.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo use it, you have to specify \u003ccode\u003eredis-cluster\u003c/code\u003e as type. Configuration is mandatory with following options in addition to the configuration options described in \u003ca href=\"#_common_settings\"\u003eCommon Settings\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003enodes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003earray of strings\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe addresses of Redis nodes to connect to.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredis-cluster\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003enodes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo:1234\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar:1234\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecredentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eusername\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${MY_REDIS_USER}\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${MY_REDIS_PASSWORD}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_redis_sentinel\"\u003eRedis Sentinel\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this type supports configuration of a Redis sentinel.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo use it, you have to specify \u003ccode\u003eredis-sentinel\u003c/code\u003e as type. Configuration is mandatory with following options in addition to the configuration options described in \u003ca href=\"#_common_settings\"\u003eCommon Settings\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003enodes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003earray of strings\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe addresses of Redis sentinel nodes to connect to.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edb\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRedis DB ID to use. Defaults to 0.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emaster\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSentinel master set name\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nSame credentials are used to connect to the sentinel service and to the Redis DB instances. This is also true if TLS client authentication is used.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredis-sentinel\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003enodes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo:1234\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar:1234\u003c/span\u003e\n \u003cspan class=\"na\"\u003edb\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e0\u003c/span\u003e\n \u003cspan class=\"na\"\u003emaster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ewhatever\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecredentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/credentials.yaml\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Operations"],"tags":null,"title":"Caching","url":"/docs/operations/cache/"},{"categories":null,"content":" Defaults The following configurations and behaviors are enforced by default:\nAll inbound communication must use TLS. TLS configuration is required for all services and endpoints exposed by heimdall. This enforcement can be disabled (not recommended) by starting Heimdall with the --insecure-skip-ingress-tls-enforcement flag.\nAll outbound communication must use TLS. TLS configuration is required for all services and endpoints heimdall communicates with. This enforcement can be disabled (not recommended) by starting Heimdall with the --insecure-skip-egress-tls-enforcement flag.\nIf Heimdall is used in proxy mode, communication with upstream services while proxying requests must use TLS. This enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-upstream-tls-enforcement flag.\nConfiguring the trusted_proxies property to allow insecure networks (0.0.0.0/0, 0/0, 0000:0000:0000:0000:0000:0000:0000:0000/0, and ::/0) is prohibited. See also HTTP Header Security Considerations. This enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-secure-trusted-proxies-enforcement flag.\nThe authentication stage of the default rule cannot start with an insecure authenticator (i.e., authenticators that allow all requests to pass through). This enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-secure-default-rule-enforcement flag.\nFor development purposes, all of the above settings can be disabled at once by starting heimdall with the --insecure flag.\nIf any of the above enforcement settings are disabled and an insecure configuration is used, warnings will be logged.\nHTTP Header Security Considerations If trusted_proxies property is configured (see also the corresponding configuration options) to let heimdall make use of different HTTP headers to build the URL for rule and HTTP method matching purposes, following logic apply:\nThe value for the used HTTP scheme is taken from the X-Forwarded-Proto header.\nThe value for the used HTTP host and port is taken from the X-Forwarded-Host header.\nThe value for the used HTTP path is taken from X-Forwarded-Uri header, which may also contain query parameters.\nThe value for the used HTTP method is taken from the X-Forwarded-Method header.\nIf the evaluation result for any of the above said steps is empty, the corresponding value is taken from the actual request to heimdall. E.g. if X-Forwarded-Method is set, the HTTP method used to communicate with heimdall is used for rule matching respectively evaluation purposes.\nThat means, if the client integrating with heimdall does not make use of the above said headers and does not drop them, a malicious actor could spoof them most probably leading to privileges escalation (depending on your rules). To avoid such situations, please adhere to the following practices:\nIf you can, try avoiding usage of trusted_proxies. Nothing can be spoofed then. However, you will lose the information about the used HTTP scheme, host and port and cannot rely on these in your rules.\nConfigure all headers and use those taking precedence. That is, always set X-Forwarded-Method, X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Uri.\nIf you cannot influence, which headers are set by your system, you’re integrating with heimdall, let it drop unused ones. E.g. If the proxy forwarding the request to heimdall by default sets only X-Forwarded-Proto and X-Forwarded-Host, let it drop the X-Forwarded-Method and X-Forwarded-Uri headers.\nThe API Gateways \u0026amp; Proxies Guides follow these practices, respectively highlight where caution is required. So, you can find examples there.\nObservability Information Logs, metrics and profiling information is very valuable for operating heimdall. These are however also very valuable for any adversary. For this reason, the corresponding services, exposing such information are by default, if enabled, listening only on the loopback (127.0.0.1) interface. If you have to configure them to listen to other interfaces, e.g. because you operate heimdall in a container, make sure, you don’t expose them publicly.\nTLS Trust Store As documented in Concepts section, the execution of heimdall’s pipeline typically includes communication to other systems. The endpoints of the corresponding systems should be TLS protected. This is however actually out of scope for heimdall. What is in scope, is the verification of the used TLS server certificate if TLS is used. This happens by making use of the operating system-wide trust store, containing the certificates of Root and Intermediate CAs (trust anchors) shipped with the OS. That means, you should\nensure this trust store contains the certificates of the Root CAs of your PKI hierarchy and\nensure the endpoints, heimdall communicates with over TLS, provide not only their own certificates, but also the intermediate certificates and cross certificates not included within the OS trust store\nBoth is required to enable heimdall building the certificate chain for TLS server certificate verification purpose. If heimdall fails doing so, the connection will be dropped.\nAs written above, heimdall makes use of the OS wide trust store to build the certificate chain. The most common installation directory on a Linux system for that trust store is the /etc/ssl/certs directory. In addition to the separate root and intermediate CA certificates, it also contains a ca-certificates.crt file, containing all installed certificates as well. This file is used by heimdall for the aforesaid purpose.\nheimdall container image is shipped without any certificates by intention to ensure you take care about the up-to-date status of the trust store. This way, if you use heimdall in a container, you have to mount the OS trust store into heimdall’s container to enable its usage.\nE.g.\ndocker run -t -p 4455:4455 \\ -v $PWD:/heimdall/conf \\ -v /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro \\ dadrus/heimdall:dev serve decision \\ -c /heimdall/conf/heimdall.yaml The verification of TLS server certificates is not the single configuration option. You should also ensure heimdall’s services, you’re using, are configured to be available via TLS as well. See TLS Configuration for all available options.\nSecurity Considerations In a typical production scenario, there is a need for proper key and certificate management. This is supported by heimdall in the following way:\nyou can and should configure not only the private key for signature creation purposes, but also the corresponding certificate chain. This way your upstream services are able not only to verify the signatures of the signed objects for cryptographic validity, but also perform verification of the revocation status of used certificates and also their time validity. All of that is crucial for secure communication.\nThe cryptographic material for the above said verification purposes is available via the JWKS endpoint for the upstream services.\nyou can configure multiple keys in heimdall’s key_store and specify the key_id of the key to use. The easiest way to let heimdall use the key id, you need, is to set X-Key-ID header in the PEM block of the corresponding private key (as also shown in the example above). Usage of key ids allows for seamless key rotation in setups which do not support or allow usage of secret management systems, respectively hot reloading of the corresponding updates by heimdall.\nSecret Management \u0026amp; Rotation When configuring heimdall, there are many places requiring secrets, like passwords, tokens, key material, etc. While you can directly configure these in heimdall’s config file, there is a huge chance for leaking them. Please reference the secrets in the config file via environment variables, or make use of external files where possible instead, and let the contents of these be managed by a secret management system.\nUsage of external files can even allow you to rotate the configured secrets without the need to restart heimdall if desired. Watching for secrets rotation is however disabled by default, but can be enabled by setting the secrets_reload_enabled property to true on the top level of heimdall’s configuration.\nAs of today secret reloading is only supported for key stores and Redis cache backend credentials. Verifying Heimdall Binaries and Container Images Heimdall binaries and container images are signed using Cosign and the keyless signing feature.\nPrerequisites Install Cosign\nContainer Image Signature Verification The signatures are stored in a repository named dadrus/heimdall-signatures. To verify the container image using Cosign, execute the following command:\nCOSIGN_REPOSITORY=dadrus/heimdall-signatures \\ cosign verify dadrus/heimdall:\u0026lt;tag\u0026gt; \\ --certificate-identity-regexp=https://github.com/dadrus/heimdall/.github/workflows/ci.yaml* \\ --certificate-oidc-issuer=https://token.actions.githubusercontent.com | jq If you pull heimdall images from ghcr.io, reference the ghcr.io registry while specifying the repository names. So dadrus/heimdall-signatures becomes ghcr.io/dadrus/heimdall-signatures and dadrus/heimdall:\u0026lt;tag\u0026gt; becomes ghcr.io/dadrus/heimdall:\u0026lt;tag\u0026gt;. In successful verification case, cosign will print similar output to the one shown below and exit with 0.\n[ { \u0026#34;critical\u0026#34;: { \u0026#34;identity\u0026#34;: { \u0026#34;docker-reference\u0026#34;: \u0026#34;index.docker.io/dadrus/heimdall\u0026#34; }, \u0026#34;image\u0026#34;: { \u0026#34;docker-manifest-digest\u0026#34;: \u0026#34;sha256:289b1a3eeeceeef08362a6fbcf4b95e726686d17998798e149c30b6974728eaf\u0026#34; }, \u0026#34;type\u0026#34;: \u0026#34;cosign container image signature\u0026#34; }, \u0026#34;optional\u0026#34;: { \u0026#34;1.3.6.1.4.1.57264.1.1\u0026#34;: \u0026#34;https://token.actions.githubusercontent.com\u0026#34;, \u0026#34;1.3.6.1.4.1.57264.1.2\u0026#34;: \u0026#34;push\u0026#34;, \u0026#34;1.3.6.1.4.1.57264.1.3\u0026#34;: \u0026#34;04379639dc5f3fbfc260e883ee4938a35076d63e\u0026#34;, \u0026#34;1.3.6.1.4.1.57264.1.4\u0026#34;: \u0026#34;CI\u0026#34;, \u0026#34;1.3.6.1.4.1.57264.1.5\u0026#34;: \u0026#34;dadrus/heimdall\u0026#34;, \u0026#34;1.3.6.1.4.1.57264.1.6\u0026#34;: \u0026#34;refs/heads/main\u0026#34;, \u0026#34;Bundle\u0026#34;: { \u0026#34;SignedEntryTimestamp\u0026#34;: \u0026#34;MEUCIFIvxs30zysroG6ItUNL+hfE3Cxn4GuiQe8d1u5N27OEAiEAqmzLrw80846U53nL/jtQ3U/2yx8Jqu8H75g6sihIcpg=\u0026#34;, \u0026#34;Payload\u0026#34;: { \u0026#34;body\u0026#34;: \u0026#34;eyJhcGlWZXJzaW9uIjoi...xTMHRMUW89In19fX0=\u0026#34;, \u0026#34;integratedTime\u0026#34;: 1692727396, \u0026#34;logIndex\u0026#34;: 32332529, \u0026#34;logID\u0026#34;: \u0026#34;c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d\u0026#34; } }, \u0026#34;Issuer\u0026#34;: \u0026#34;https://token.actions.githubusercontent.com\u0026#34;, \u0026#34;Subject\u0026#34;: \u0026#34;https://github.com/dadrus/heimdall/.github/workflows/ci.yaml@refs/heads/main\u0026#34;, \u0026#34;githubWorkflowName\u0026#34;: \u0026#34;CI\u0026#34;, \u0026#34;githubWorkflowRef\u0026#34;: \u0026#34;refs/heads/main\u0026#34;, \u0026#34;githubWorkflowRepository\u0026#34;: \u0026#34;dadrus/heimdall\u0026#34;, \u0026#34;githubWorkflowSha\u0026#34;: \u0026#34;04379639dc5f3fbfc260e883ee4938a35076d63e\u0026#34;, \u0026#34;githubWorkflowTrigger\u0026#34;: \u0026#34;push\u0026#34; } } ] For released images, the Subject value ends with @refs/tags/\u0026lt;release version\u0026gt;.\nRelease Binary Signature Verification The detached signatures, as well as certificates for all released archives are published together with the corresponding platform specific archive. The names of the signature files adhere to the \u0026lt;archive\u0026gt;-keyless.sig name pattern and the names of the certificate files adhere to the \u0026lt;archive\u0026gt;-keyless.pem name pattern, with \u0026lt;archive\u0026gt; being the archive for a platform specific build.\nTo verify the signature of the archive, hence its contents including the platform specific heimdall binary with Cosign execute the following command:\ncosign verify-blob /path/to/the/downloaded/\u0026lt;archive\u0026gt; \\ --certificate-identity-regexp=https://github.com/dadrus/heimdall/.github/workflows/ci.yaml* \\ --certificate-oidc-issuer=https://token.actions.githubusercontent.com \\ --signature /path/to/the/downloaded/\u0026lt;archive\u0026gt;-keyless.sig \\ --certificate /path/to/the/downloaded/\u0026lt;archive\u0026gt;--keyless.pem In successful verification case, cosign will print the following output and exit with 0.\nVerified OK Software Bill of Material (SBOM) Heimdall is shipped with an SBOM in CyclonDX (json) format.\nIf you use a released binary of heimdall, the corresponding file is part of the platform specific archive. That way, if you verify the signature of the archive (see above), you do also get evidence about the validity of the SBOM.\nIf you use a container image, the same SBOM is attached to the image as attestation signed with Cosign. These attestations are stored in the dadrus/heimdall-sbom repository. To verify the attestation and retrieve the SBOM execute the following command once Cosign is installed:\nCOSIGN_REPOSITORY=dadrus/heimdall-sbom \\ cosign verify-attestation dadrus/heimdall:\u0026lt;tag\u0026gt; \\ --certificate-identity-regexp=https://github.com/dadrus/heimdall/.github/workflows/ci.yaml* \\ --certificate-oidc-issuer=https://token.actions.githubusercontent.com \\ --type=cyclonedx If you pull heimdall images from ghcr.io, reference the ghcr.io registry while specifying the repository names. So dadrus/heimdall-sbom becomes ghcr.io/dadrus/heimdall-sbom and dadrus/heimdall:\u0026lt;tag\u0026gt; becomes ghcr.io/dadrus/heimdall:\u0026lt;tag\u0026gt;. In successful verification case, cosign will print similar output to the one shown below and exit with 0.\n{ \u0026#34;payloadType\u0026#34;: \u0026#34;application/vnd.in-toto+json\u0026#34;, \u0026#34;payload\u0026#34;: \u0026#34;eyJfdHlwZSI6Imh...LCJ2ZXJzaW9uIjoxfX0=\u0026#34;, \u0026#34;signatures\u0026#34;: [ { \u0026#34;keyid\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;sig\u0026#34;: \u0026#34;MEQCICGdo9hmIUrBRzVQ23VS...6ToNGa5YrommZNCQ==\u0026#34; } ] } Here, payload is the base64 encoded attestation value embedding the SBOM.\nAs one-liner, you can verify the signature and extract the SBOM as follows:\nCOSIGN_REPOSITORY=dadrus/heimdall-sbom \\ cosign verify-attestation dadrus/heimdall:\u0026lt;tag\u0026gt; \\ --certificate-identity-regexp=https://github.com/dadrus/heimdall/.github/workflows/ci.yaml* \\ --certificate-oidc-issuer=https://token.actions.githubusercontent.com \\ --type=cyclonedx | jq -r \u0026#34;.payload\u0026#34; | base64 -d | jq -r \u0026#34;.predicate\u0026#34; \u0026gt; heimdall.sbom.json The result will be the heimdall.sbom.json SBOM document, which you can use with any SCA or monitoring tool of your choice, e.g. Dependency Track.\n","description":"To operate heimdall in a secure way, you should configure heimdall accordingly. Following sections address the corresponding areas.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_defaults\"\u003eDefaults\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following configurations and behaviors are enforced by default:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eAll inbound communication must use TLS. TLS configuration is required for all services and endpoints exposed by heimdall. This enforcement can be disabled (not recommended) by starting Heimdall with the \u003ccode\u003e--insecure-skip-ingress-tls-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAll outbound communication must use TLS. TLS configuration is required for all services and endpoints heimdall communicates with. This enforcement can be disabled (not recommended) by starting Heimdall with the \u003ccode\u003e--insecure-skip-egress-tls-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf Heimdall is used in \u003ca href=\"/docs/concepts/operating_modes/#_proxy_mode\"\u003eproxy mode\u003c/a\u003e, communication with upstream services while proxying requests must use TLS. This enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-upstream-tls-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eConfiguring the \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003e\u003ccode\u003etrusted_proxies\u003c/code\u003e\u003c/a\u003e property to allow insecure networks (\u003ccode\u003e0.0.0.0/0\u003c/code\u003e, \u003ccode\u003e0/0\u003c/code\u003e, \u003ccode\u003e0000:0000:0000:0000:0000:0000:0000:0000/0\u003c/code\u003e, and \u003ccode\u003e::/0\u003c/code\u003e) is prohibited. See also \u003ca href=\"/docs/operations/security/#_http_header_security_considerations\"\u003eHTTP Header Security Considerations\u003c/a\u003e. This enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-secure-trusted-proxies-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe authentication stage of the \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e cannot start with an insecure authenticator (i.e., authenticators that allow all requests to pass through). This enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-secure-default-rule-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor development purposes, all of the above settings can be disabled at once by starting heimdall with the \u003ccode\u003e--insecure\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf any of the above enforcement settings are disabled and an insecure configuration is used, warnings will be logged.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_http_header_security_considerations\"\u003eHTTP Header Security Considerations\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf \u003ccode\u003etrusted_proxies\u003c/code\u003e property is configured (see also the corresponding \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003econfiguration options\u003c/a\u003e) to let heimdall make use of different HTTP headers to build the URL for rule and HTTP method matching purposes, following logic apply:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eThe value for the used HTTP scheme is taken from the \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe value for the used HTTP host and port is taken from the \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe value for the used HTTP path is taken from \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e header, which may also contain query parameters.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe value for the used HTTP method is taken from the \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e header.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the evaluation result for any of the above said steps is empty, the corresponding value is taken from the actual request to heimdall. E.g. if \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e is set, the HTTP method used to communicate with heimdall is used for rule matching respectively evaluation purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThat means, if the client integrating with heimdall does not make use of the above said headers and does not drop them, a malicious actor could spoof them most probably leading to privileges escalation (depending on your rules). To avoid such situations, please adhere to the following practices:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIf you can, try avoiding usage of \u003ccode\u003etrusted_proxies\u003c/code\u003e. Nothing can be spoofed then. However, you will lose the information about the used HTTP scheme, host and port and cannot rely on these in your rules.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eConfigure all headers and use those taking precedence. That is, always set \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf you cannot influence, which headers are set by your system, you’re integrating with heimdall, let it drop unused ones. E.g. If the proxy forwarding the request to heimdall by default sets only \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e and \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e, let it drop the \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e and \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e headers.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"/guides/proxies/\"\u003eAPI Gateways \u0026amp; Proxies Guides\u003c/a\u003e follow these practices, respectively highlight where caution is required. So, you can find examples there.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_observability_information\"\u003eObservability Information\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eLogs, metrics and profiling information is very valuable for operating heimdall. These are however also very valuable for any adversary. For this reason, the corresponding services, exposing such information are by default, if enabled, listening only on the loopback (\u003ccode\u003e127.0.0.1\u003c/code\u003e) interface. If you have to configure them to listen to other interfaces, e.g. because you operate heimdall in a container, make sure, you don’t expose them publicly.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_tls_trust_store\"\u003eTLS Trust Store\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs documented in \u003ca href=\"/docs/concepts/pipelines/\"\u003eConcepts\u003c/a\u003e section, the execution of heimdall’s pipeline typically includes communication to other systems. The endpoints of the corresponding systems should be TLS protected. This is however actually out of scope for heimdall. What is in scope, is the verification of the used TLS server certificate if TLS is used. This happens by making use of the operating system-wide trust store, containing the certificates of Root and Intermediate CAs (trust anchors) shipped with the OS. That means, you should\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eensure this trust store contains the certificates of the Root CAs of your PKI hierarchy and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eensure the endpoints, heimdall communicates with over TLS, provide not only their own certificates, but also the intermediate certificates and cross certificates not included within the OS trust store\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBoth is required to enable heimdall building the certificate chain for TLS server certificate verification purpose. If heimdall fails doing so, the connection will be dropped.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs written above, heimdall makes use of the OS wide trust store to build the certificate chain. The most common installation directory on a Linux system for that trust store is the \u003ccode\u003e/etc/ssl/certs\u003c/code\u003e directory. In addition to the separate root and intermediate CA certificates, it also contains a \u003ccode\u003eca-certificates.crt\u003c/code\u003e file, containing all installed certificates as well. This file is used by heimdall for the aforesaid purpose.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eheimdall container image is shipped without any certificates by intention to ensure you take care about the up-to-date status of the trust store. This way, if you use heimdall in a container, you have to mount the OS trust store into heimdall’s container to enable its usage.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003edocker run \u003cspan class=\"nt\"\u003e-t\u003c/span\u003e \u003cspan class=\"nt\"\u003e-p\u003c/span\u003e 4455:4455 \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-v\u003c/span\u003e \u003cspan class=\"nv\"\u003e$PWD\u003c/span\u003e:/heimdall/conf \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-v\u003c/span\u003e /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n dadrus/heimdall:dev serve decision \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-c\u003c/span\u003e /heimdall/conf/heimdall.yaml\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe verification of TLS server certificates is not the single configuration option. You should also ensure heimdall’s services, you’re using, are configured to be available via TLS as well. See \u003ca href=\"/docs/configuration/types/#_tls\"\u003eTLS Configuration\u003c/a\u003e for all available options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_security_considerations\"\u003eSecurity Considerations\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn a typical production scenario, there is a need for proper key and certificate management. This is supported by heimdall in the following way:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eyou can and should configure not only the private key for signature creation purposes, but also the corresponding certificate chain. This way your upstream services are able not only to verify the signatures of the signed objects for cryptographic validity, but also perform verification of the revocation status of used certificates and also their time validity. All of that is crucial for secure communication.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe cryptographic material for the above said verification purposes is available via the \u003ca href=\"/openapi/#tag/Well-Known/operation/well_known_jwks\"\u003eJWKS endpoint\u003c/a\u003e for the upstream services.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eyou can configure multiple keys in heimdall’s \u003ccode\u003ekey_store\u003c/code\u003e and specify the \u003ccode\u003ekey_id\u003c/code\u003e of the key to use. The easiest way to let heimdall use the key id, you need, is to set \u003ccode\u003eX-Key-ID\u003c/code\u003e header in the PEM block of the corresponding private key (as also shown in the example above). Usage of key ids allows for seamless key rotation in setups which do not support or allow usage of secret management systems, respectively hot reloading of the corresponding updates by heimdall.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_secret_management_rotation\"\u003eSecret Management \u0026amp; Rotation\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhen configuring heimdall, there are many places requiring secrets, like passwords, tokens, key material, etc. While you can directly configure these in heimdall’s config file, there is a huge chance for leaking them. Please reference the secrets in the config file via \u003ca href=\"/docs/operations/configuration/#_configuration_file\"\u003eenvironment variables\u003c/a\u003e, or make use of external files where possible instead, and let the contents of these be managed by a secret management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUsage of external files can even allow you to rotate the configured secrets without the need to restart heimdall if desired. Watching for secrets rotation is however disabled by default, but can be enabled by setting the \u003ccode\u003esecrets_reload_enabled\u003c/code\u003e property to \u003ccode\u003etrue\u003c/code\u003e on the top level of heimdall’s configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAs of today secret reloading is only supported for \u003ca href=\"/docs/configuration/types/#_key_store\"\u003ekey stores\u003c/a\u003e and \u003ca href=\"/docs/operations/cache/#_common_settings\"\u003eRedis cache backend credentials\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_verifying_heimdall_binaries_and_container_images\"\u003eVerifying Heimdall Binaries and Container Images\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall binaries and container images are signed using \u003ca href=\"https://docs.sigstore.dev/docs/signing/quickstart/\"\u003eCosign\u003c/a\u003e and the \u003ca href=\"https://docs.sigstore.dev/docs/signing/overview/\"\u003ekeyless signing feature\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_prerequisites\"\u003ePrerequisites\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eInstall \u003ca href=\"https://docs.sigstore.dev/docs/system_config/installation/\"\u003eCosign\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_container_image_signature_verification\"\u003eContainer Image Signature Verification\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe signatures are stored in a repository named \u003ccode\u003edadrus/heimdall-signatures\u003c/code\u003e. To verify the container image using Cosign, execute the following command:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eCOSIGN_REPOSITORY\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003edadrus/heimdall-signatures \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\ncosign verify dadrus/heimdall:\u0026lt;tag\u0026gt; \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-identity-regexp\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://github.com/dadrus/heimdall/.github/workflows/ci.yaml\u003cspan class=\"k\"\u003e*\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-oidc-issuer\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://token.actions.githubusercontent.com | jq\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you pull heimdall images from ghcr.io, reference the \u003ccode\u003eghcr.io\u003c/code\u003e registry while specifying the repository names. So \u003ccode\u003edadrus/heimdall-signatures\u003c/code\u003e becomes \u003ccode\u003eghcr.io/dadrus/heimdall-signatures\u003c/code\u003e and \u003ccode\u003edadrus/heimdall:\u0026lt;tag\u0026gt;\u003c/code\u003e becomes \u003ccode\u003eghcr.io/dadrus/heimdall:\u0026lt;tag\u0026gt;\u003c/code\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn successful verification case, cosign will print similar output to the one shown below and exit with \u003ccode\u003e0\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;critical\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;identity\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;docker-reference\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;index.docker.io/dadrus/heimdall\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e},\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;image\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;docker-manifest-digest\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;sha256:289b1a3eeeceeef08362a6fbcf4b95e726686d17998798e149c30b6974728eaf\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e},\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;type\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;cosign container image signature\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e},\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;optional\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://token.actions.githubusercontent.com\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;push\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.3\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;04379639dc5f3fbfc260e883ee4938a35076d63e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.4\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;CI\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.5\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;dadrus/heimdall\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.6\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;refs/heads/main\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;Bundle\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;SignedEntryTimestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;MEUCIFIvxs30zysroG6ItUNL+hfE3Cxn4GuiQe8d1u5N27OEAiEAqmzLrw80846U53nL/jtQ3U/2yx8Jqu8H75g6sihIcpg=\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;Payload\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;body\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;eyJhcGlWZXJzaW9uIjoi...xTMHRMUW89In19fX0=\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;integratedTime\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1692727396\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;logIndex\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e32332529\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;logID\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e},\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;Issuer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://token.actions.githubusercontent.com\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;Subject\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://github.com/dadrus/heimdall/.github/workflows/ci.yaml@refs/heads/main\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;githubWorkflowName\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;CI\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;githubWorkflowRef\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;refs/heads/main\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;githubWorkflowRepository\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;dadrus/heimdall\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;githubWorkflowSha\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;04379639dc5f3fbfc260e883ee4938a35076d63e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;githubWorkflowTrigger\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;push\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor released images, the \u003ccode\u003eSubject\u003c/code\u003e value ends with \u003ccode\u003e@refs/tags/\u0026lt;release version\u0026gt;\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_release_binary_signature_verification\"\u003eRelease Binary Signature Verification\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe detached signatures, as well as certificates for all released archives are published together with the corresponding platform specific archive. The names of the signature files adhere to the \u003ccode\u003e\u0026lt;archive\u0026gt;-keyless.sig\u003c/code\u003e name pattern and the names of the certificate files adhere to the \u003ccode\u003e\u0026lt;archive\u0026gt;-keyless.pem\u003c/code\u003e name pattern, with \u003ccode\u003e\u0026lt;archive\u0026gt;\u003c/code\u003e being the archive for a platform specific build.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo verify the signature of the archive, hence its contents including the platform specific heimdall binary with Cosign execute the following command:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003ecosign verify-blob /path/to/the/downloaded/\u0026lt;archive\u0026gt; \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-identity-regexp\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://github.com/dadrus/heimdall/.github/workflows/ci.yaml\u003cspan class=\"k\"\u003e*\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-oidc-issuer\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://token.actions.githubusercontent.com \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--signature\u003c/span\u003e /path/to/the/downloaded/\u0026lt;archive\u0026gt;-keyless.sig \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate\u003c/span\u003e /path/to/the/downloaded/\u0026lt;archive\u0026gt;--keyless.pem\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn successful verification case, cosign will print the following output and exit with \u003ccode\u003e0\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eVerified OK\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_software_bill_of_material_sbom\"\u003eSoftware Bill of Material (SBOM)\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall is shipped with an SBOM in \u003ca href=\"https://cyclonedx.org/\"\u003eCyclonDX\u003c/a\u003e (json) format.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you use a released binary of heimdall, the corresponding file is part of the platform specific archive. That way, if you verify the signature of the archive (see above), you do also get evidence about the validity of the SBOM.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you use a container image, the same SBOM is attached to the image as attestation signed with Cosign. These attestations are stored in the \u003ccode\u003edadrus/heimdall-sbom\u003c/code\u003e repository. To verify the attestation and retrieve the SBOM execute the following command once Cosign is installed:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eCOSIGN_REPOSITORY\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003edadrus/heimdall-sbom \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\ncosign verify-attestation dadrus/heimdall:\u0026lt;tag\u0026gt; \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-identity-regexp\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://github.com/dadrus/heimdall/.github/workflows/ci.yaml\u003cspan class=\"k\"\u003e*\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-oidc-issuer\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://token.actions.githubusercontent.com \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--type\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ecyclonedx\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you pull heimdall images from ghcr.io, reference the \u003ccode\u003eghcr.io\u003c/code\u003e registry while specifying the repository names. So \u003ccode\u003edadrus/heimdall-sbom\u003c/code\u003e becomes \u003ccode\u003eghcr.io/dadrus/heimdall-sbom\u003c/code\u003e and \u003ccode\u003edadrus/heimdall:\u0026lt;tag\u0026gt;\u003c/code\u003e becomes \u003ccode\u003eghcr.io/dadrus/heimdall:\u0026lt;tag\u0026gt;\u003c/code\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn successful verification case, cosign will print similar output to the one shown below and exit with \u003ccode\u003e0\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;payloadType\u0026#34;\u003c/span\u003e: \u003cspan class=\"s2\"\u003e\u0026#34;application/vnd.in-toto+json\u0026#34;\u003c/span\u003e,\n \u003cspan class=\"s2\"\u003e\u0026#34;payload\u0026#34;\u003c/span\u003e: \u003cspan class=\"s2\"\u003e\u0026#34;eyJfdHlwZSI6Imh...LCJ2ZXJzaW9uIjoxfX0=\u0026#34;\u003c/span\u003e,\n \u003cspan class=\"s2\"\u003e\u0026#34;signatures\u0026#34;\u003c/span\u003e: \u003cspan class=\"o\"\u003e[\u003c/span\u003e\n \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;keyid\u0026#34;\u003c/span\u003e: \u003cspan class=\"s2\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e,\n \u003cspan class=\"s2\"\u003e\u0026#34;sig\u0026#34;\u003c/span\u003e: \u003cspan class=\"s2\"\u003e\u0026#34;MEQCICGdo9hmIUrBRzVQ23VS...6ToNGa5YrommZNCQ==\u0026#34;\u003c/span\u003e\n \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"o\"\u003e]\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, \u003ccode\u003epayload\u003c/code\u003e is the base64 encoded attestation value embedding the SBOM.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs one-liner, you can verify the signature and extract the SBOM as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eCOSIGN_REPOSITORY\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003edadrus/heimdall-sbom \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\ncosign verify-attestation dadrus/heimdall:\u0026lt;tag\u0026gt; \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-identity-regexp\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://github.com/dadrus/heimdall/.github/workflows/ci.yaml\u003cspan class=\"k\"\u003e*\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-oidc-issuer\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://token.actions.githubusercontent.com \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--type\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ecyclonedx | jq \u003cspan class=\"nt\"\u003e-r\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;.payload\u0026#34;\u003c/span\u003e | \u003cspan class=\"nb\"\u003ebase64\u003c/span\u003e \u003cspan class=\"nt\"\u003e-d\u003c/span\u003e | jq \u003cspan class=\"nt\"\u003e-r\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;.predicate\u0026#34;\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e heimdall.sbom.json\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe result will be the \u003ccode\u003eheimdall.sbom.json\u003c/code\u003e SBOM document, which you can use with any SCA or monitoring tool of your choice, e.g. \u003ca href=\"https://dependencytrack.org/\"\u003eDependency Track\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Operations"],"tags":null,"title":"Security","url":"/docs/operations/security/"},{"categories":null,"content":" To make use of this service you have to start heimdall with either heimdall serve proxy or heimdall serve decision. By default, heimdall listens on 0.0.0.0:4455 endpoint for incoming requests and also configures useful defaults. You can, and should however adjust the configuration for your needs.\nConfiguration The configuration of this service can be adjusted in the serve property, which lives on the top level of heimdall’s configuration and supports the following properties.\nhost: string (optional)\nBy making use of this property, you can specify the TCP/IP address on which heimdall should listen for connections from client applications. The entry 0.0.0.0 allows listening for all IPv4 addresses. 0.0.0.0 is also the default setting.\nport: integer (optional)\nBy making use of this property, you can specify the TCP port that heimdall should listen on. Defaults to 4455.\ntimeout: Timeout (optional)\nBy using this property, you can override the default timeouts used by heimdall. Following properties are supported:\nidle: Duration (optional)\nThe maximum amount of time to wait for the next request when keep-alive is enabled. If set to 0, the value of the read timeout is used. Defaults to 2 minutes. If heimdall is operated in proxy mode, this value is also used for the maximum amount of time an idle (keep-alive) connection to the upstream will remain idle before closing itself.\nread: Duration (optional)\nThe absolute amount of time allowed to read the entire request, including body. Defaults to 5 seconds. If heimdall is operated in proxy mode, the read timeout is also used while waiting for the responses from the upstream service. Here it specifies the amount of time to wait for a server’s response headers after fully writing the request (including its body, if any). Upon successful upgrade responses from the upstream service, this timeout is disabled, allowing e.g. for WebSockets proxying. Setting this property to 0s will disable the timeout.\nSetting this timeout to 0 will make heimdall vulnerable to Slowloris attacks). write: Duration (optional)\nThe maximum duration before timing out writes of the response. Defaults to 10 seconds. Setting this property to 0s will disable the timeout. Compared to the read timeout, the write timeout is not absolute and resets each time data is written to the output stream if heimdall is operated in proxy mode. This allows Server-Sent-Events and other unidirectional communication without the need to extend the timeout. As with the read timeout, this timeout is disabled upon successful upgrade responses from the upstream service, allowing e.g. for WebSockets proxying.\nbuffer_limit: BufferLimit (optional)\nBuffer limits for inbound requests and outbound responses.\nread: ByteSize (optional)\nThe maximum size for the read buffer allowed to read the full request including body. Defaults to 4KB.\nwrite: ByteSize (optional)\nThe maximum size for the write buffer of the response. Defaults to 4KB.\nconnections_limit: ConnectionsLimit (optional)\nIf heimdall is operated in proxy mode, this property configures allowed connections limit per upstream service (ignored in decision mode). Following limits can be configured:\nmax_per_host: integer (optional)\nLimits the total number of connections per host, including connections in the dialing, active, and idle states. On limit violation, dials will block. Defaults to 0, which means there is no limit.\nmax_idle: integer (optional)\nControls the maximum number of idle (keep-alive) connections across all hosts. 0 means no limit. Defaults to 100.\nmax_idle_per_host: integer (optional)\nControls the maximum number of idle (keep-alive) connections per host. Defaults to 100. Cannot exceed the value of max_idle.\ncors: CORS (optional)\nCORS (Cross-Origin Resource Sharing) headers can be added and configured by making use of this option. This functionality allows for advanced security features to quickly be set. If CORS headers are set, then heimdall does not pass preflight requests neither to its pipeline, nor to the upstream service. Instead, the response will be generated and sent back to the client directly.\ntls: TLS (optional)\nTLS-related configuration to ensure secure communication.\nAlthough this property is optional, heimdall enforces its usage by default. This enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-ingress-tls-enforcement flag. trusted_proxies: string array (optional)\nheimdall can process X-Forwarded-* headers, such as X-Forwarded-For, X-Forwarded-Method, etc., as well as the Forwarded header sent by its clients. Additionally, heimdall can forward some of these headers (X-Forwarded-For and Forwarded) to the configured upstream services. However, since these headers can easily be spoofed, they are only used when the request originates from a trusted source. This is typically the case when heimdall operates behind another proxy. For example, while the Host HTTP header is usually used to determine the client’s requested host, when heimdall is behind a proxy, the actual host of the ultimate client may be stored in an X-Forwarded-Host header, which, however, can also be spoofed.\nDepending on your setup, you may need to rely on these headers. In such cases, you must configure the trusted_proxies option and specify the IP addresses or IP ranges (in CIDR notation) of the proxies in front of heimdall. If this option is not configured, heimdall will reject these headers from all clients to prevent spoofing, as improper use could lead to privilege escalation.\nBe sure to review the security implications before enabling this property. heimdall does not allow configuring this property to accept these headers from any sources. Specifically, the networks 0.0.0.0/0, 0/0, 0000:0000:0000:0000:0000:0000:0000:0000/0, and ::/0 are disallowed by default. This enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-secure-trusted-proxies-enforcement flag if necessary. respond: Respond (optional)\nBy making use of this property, you can instruct heimdall to preserve error information and provide it in the response body to the caller, as well as to use HTTP status codes deviating from those heimdall would usually use.\nThis mapping is only applicable if the HTTP status code is set by heimdall and not by the upstream service in the response to the proxied request. For that reason, you cannot configure the mapping for the accepted response (it will be ignored). Example 1. Complex proxy service configuration. serve: host: 172.17.0.2 tls: key_store: path: /path/to/keystore.pem password: VerySecure! timeout: read: 1s write: 2s idle: 30s connections_limit: max_per_host: 20 max_idle: 100 max_idle_per_host: 10 buffer_limit: read: 4KB write: 10KB trusted_proxies: - 192.168.1.0/24 cors: allowed_origins: - example.org allowed_methods: - HEAD - PATCH allow_credentials: true max_age: 10s respond: verbose: true with: authentication_error: code: 404 authorization_error: code: 404 ","description":"This is heimdall's main service responsible for driving the actual access control decision process.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo make use of this service you have to start heimdall with either \u003ccode\u003eheimdall serve proxy\u003c/code\u003e or \u003ccode\u003eheimdall serve decision\u003c/code\u003e. By default, heimdall listens on \u003ccode\u003e0.0.0.0:4455\u003c/code\u003e endpoint for incoming requests and also configures useful defaults. You can, and should however adjust the configuration for your needs.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration\"\u003eConfiguration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this service can be adjusted in the \u003ccode\u003eserve\u003c/code\u003e property, which lives on the top level of heimdall’s configuration and supports the following properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehost\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can specify the TCP/IP address on which heimdall should listen for connections from client applications. The entry \u003ccode\u003e0.0.0.0\u003c/code\u003e allows listening for all IPv4 addresses. \u003ccode\u003e0.0.0.0\u003c/code\u003e is also the default setting.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eport\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can specify the TCP port that heimdall should listen on. Defaults to \u003ccode\u003e4455\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etimeout\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eTimeout\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy using this property, you can override the default timeouts used by heimdall. Following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eidle\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum amount of time to wait for the next request when keep-alive is enabled. If set to 0, the value of the \u003ccode\u003eread\u003c/code\u003e timeout is used. Defaults to 2 minutes. If heimdall is operated in proxy mode, this value is also used for the maximum amount of time an idle (keep-alive) connection to the upstream will remain idle before closing itself.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eread\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe absolute amount of time allowed to read the entire request, including body. Defaults to 5 seconds. If heimdall is operated in proxy mode, the \u003ccode\u003eread\u003c/code\u003e timeout is also used while waiting for the responses from the upstream service. Here it specifies the amount of time to wait for a server’s response headers after fully writing the request (including its body, if any). Upon successful upgrade responses from the upstream service, this timeout is disabled, allowing e.g. for WebSockets proxying. Setting this property to 0s will disable the timeout.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nSetting this timeout to 0 will make heimdall vulnerable to \u003ca href=\"https://en.wikipedia.org/wiki/Slowloris_(computer_security\"\u003eSlowloris attacks\u003c/a\u003e).\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum duration before timing out writes of the response. Defaults to 10 seconds. Setting this property to 0s will disable the timeout. Compared to the \u003ccode\u003eread\u003c/code\u003e timeout, the \u003ccode\u003ewrite\u003c/code\u003e timeout is not absolute and resets each time data is written to the output stream if heimdall is operated in proxy mode. This allows Server-Sent-Events and other unidirectional communication without the need to extend the timeout. As with the \u003ccode\u003eread\u003c/code\u003e timeout, this timeout is disabled upon successful upgrade responses from the upstream service, allowing e.g. for WebSockets proxying.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebuffer_limit\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eBufferLimit\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBuffer limits for inbound requests and outbound responses.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eread\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size for the read buffer allowed to read the full request including body. Defaults to 4KB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size for the write buffer of the response. Defaults to 4KB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003econnections_limit\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eConnectionsLimit\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf heimdall is operated in proxy mode, this property configures allowed connections limit per upstream service (ignored in decision mode). Following limits can be configured:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_per_host\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eLimits the total number of connections per host, including connections in the dialing, active, and idle states. On limit violation, dials will block. Defaults to 0, which means there is no limit.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_idle\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eControls the maximum number of idle (keep-alive) connections across all hosts. 0 means no limit. Defaults to 100.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_idle_per_host\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eControls the maximum number of idle (keep-alive) connections per host. Defaults to 100. Cannot exceed the value of \u003ccode\u003emax_idle\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecors\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_cors\"\u003eCORS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS\"\u003eCORS\u003c/a\u003e (Cross-Origin Resource Sharing) headers can be added and configured by making use of this option. This functionality allows for advanced security features to quickly be set. If CORS headers are set, then heimdall does not pass preflight requests neither to its pipeline, nor to the upstream service. Instead, the response will be generated and sent back to the client directly.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etls\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_tls\"\u003eTLS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTLS-related configuration to ensure secure communication.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAlthough this property is optional, heimdall enforces its usage by default. This enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-ingress-tls-enforcement\u003c/code\u003e flag.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_trusted_proxies\" class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etrusted_proxies\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eheimdall can process \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers, such as \u003ccode\u003eX-Forwarded-For\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e, etc., as well as the \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded\"\u003e\u003ccode\u003eForwarded\u003c/code\u003e\u003c/a\u003e header sent by its clients. Additionally, heimdall can forward some of these headers (\u003ccode\u003eX-Forwarded-For\u003c/code\u003e and \u003ccode\u003eForwarded\u003c/code\u003e) to the configured upstream services. However, since these headers can easily be spoofed, they are only used when the request originates from a trusted source. This is typically the case when heimdall operates behind another proxy. For example, while the \u003ccode\u003eHost\u003c/code\u003e HTTP header is usually used to determine the client’s requested host, when heimdall is behind a proxy, the actual host of the ultimate client may be stored in an \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e header, which, however, can also be spoofed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDepending on your setup, you may need to rely on these headers. In such cases, you must configure the \u003ccode\u003etrusted_proxies\u003c/code\u003e option and specify the IP addresses or IP ranges (in CIDR notation) of the proxies in front of heimdall. If this option is not configured, heimdall will reject these headers from all clients to prevent spoofing, as improper use could lead to privilege escalation.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nBe sure to review the \u003ca href=\"/docs/operations/security/#_http_header_security_considerations\"\u003esecurity implications\u003c/a\u003e before enabling this property.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nheimdall does not allow configuring this property to accept these headers from any sources. Specifically, the networks \u003ccode\u003e0.0.0.0/0\u003c/code\u003e, \u003ccode\u003e0/0\u003c/code\u003e, \u003ccode\u003e0000:0000:0000:0000:0000:0000:0000:0000/0\u003c/code\u003e, and \u003ccode\u003e::/0\u003c/code\u003e are disallowed by default. This enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-secure-trusted-proxies-enforcement\u003c/code\u003e flag if necessary.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003erespond\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_respond\"\u003eRespond\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can instruct heimdall to preserve error information and provide it in the response body to the caller, as well as to use HTTP status codes deviating from those heimdall would usually use.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis mapping is only applicable if the HTTP status code is set by heimdall and not by the upstream service in the response to the proxied request. For that reason, you cannot configure the mapping for the \u003ccode\u003eaccepted\u003c/code\u003e response (it will be ignored).\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Complex proxy service configuration.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eserve\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e172.17.0.2\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecure!\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e30s\u003c/span\u003e\n \u003cspan class=\"na\"\u003econnections_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_per_host\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e20\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_idle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e100\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_idle_per_host\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e10\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuffer_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e4KB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10KB\u003c/span\u003e\n \u003cspan class=\"na\"\u003etrusted_proxies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e192.168.1.0/24\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecors\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_origins\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eexample.org\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_methods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eHEAD\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePATCH\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_credentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_age\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\n \u003cspan class=\"na\"\u003erespond\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003everbose\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewith\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e404\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e404\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Services"],"tags":null,"title":"Main Service","url":"/docs/services/main/"},{"categories":null,"content":" By default, heimdall listens on 0.0.0.0:4457 for incoming requests and applies useful default timeouts and buffer limits. No additional options are configured by default, but you can adjust them as needed.\nThis service exposes the health and JWKS endpoints.\nConfiguration The configuration of the management endpoint is defined under the management property. It supports the following properties.\nhost: string (optional)\nUse this property to specify the TCP/IP address on which heimdall should listen for incoming connections. E.g. the entry 0.0.0.0 allows listening on all network interfaces for IPv4 and is the default setting.\nport: integer (optional)\nUse this property to specify the TCP port Heimdall should listen on. Defaults to 4457.\ntimeout: Timeout (optional)\nUse this property to override heimdall’s default timeouts. The following options are available:\nidle: Duration (optional)\nThe maximum time to wait for the next request when keep-alive is enabled. If set to 0s, the read timeout value is used. Defaults to 2 minutes.\nread: Duration (optional)\nThe maximum time allowed to read the entire request, including the body. Defaults to 5 seconds. Setting this property to 0s disables the timeout.\nwrite: Duration (optional)\nThe maximum duration before timing out response writes. Defaults to 10 seconds. Setting this property to 0s disables the timeout.\nbuffer_limit: BufferLimit (optional)\nDefines buffer limits for inbound requests and outbound responses. The following options are available:\nread: ByteSize (optional)\nThe maximum size of the read buffer for handling the full request, including the body. Defaults to 4KB.\nwrite: ByteSize (optional)\nThe maximum size of the write buffer for responses. Defaults to 4KB.\ncors: CORS (optional)\nCORS (Cross-Origin Resource Sharing) headers can be configured using this option. This allows for fine-grained security settings.\ntls: TLS (optional)\nTLS-related configuration to ensure secure communication.\nAlthough this property is optional, heimdall enforces its usage by default. This enforcement can be disabled (not recommended) by starting Heimdall with the --insecure-skip-ingress-tls-enforcement flag. Example 1. Complex management service configuration management: host: 127.0.0.1 tls: key_store: path: /path/to/keystore.pem password: VerySecure! timeout: read: 1s write: 2s idle: 30s buffer_limit: read: 4KB write: 10KB ","description":"When heimdall is started, the management service is always exposed and offers endpoints for health monitoring and retrieving keys and certificates used by Heimdall for JWT creation.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy default, heimdall listens on \u003ccode\u003e0.0.0.0:4457\u003c/code\u003e for incoming requests and applies useful default timeouts and buffer limits. No additional options are configured by default, but you can adjust them as needed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis service exposes the health and JWKS endpoints.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration\"\u003eConfiguration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of the management endpoint is defined under the \u003ccode\u003emanagement\u003c/code\u003e property. It supports the following properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehost\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUse this property to specify the TCP/IP address on which heimdall should listen for incoming connections. E.g. the entry \u003ccode\u003e0.0.0.0\u003c/code\u003e allows listening on all network interfaces for IPv4 and is the default setting.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eport\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUse this property to specify the TCP port Heimdall should listen on. Defaults to \u003ccode\u003e4457\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etimeout\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eTimeout\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUse this property to override heimdall’s default timeouts. The following options are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eidle\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum time to wait for the next request when keep-alive is enabled. If set to \u003ccode\u003e0s\u003c/code\u003e, the \u003ccode\u003eread\u003c/code\u003e timeout value is used. Defaults to 2 minutes.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eread\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum time allowed to read the entire request, including the body. Defaults to 5 seconds. Setting this property to \u003ccode\u003e0s\u003c/code\u003e disables the timeout.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum duration before timing out response writes. Defaults to 10 seconds. Setting this property to \u003ccode\u003e0s\u003c/code\u003e disables the timeout.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebuffer_limit\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eBufferLimit\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines buffer limits for inbound requests and outbound responses. The following options are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eread\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size of the read buffer for handling the full request, including the body. Defaults to 4KB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size of the write buffer for responses. Defaults to 4KB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecors\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_cors\"\u003eCORS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS\"\u003eCORS\u003c/a\u003e (Cross-Origin Resource Sharing) headers can be configured using this option. This allows for fine-grained security settings.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etls\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_tls\"\u003eTLS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTLS-related configuration to ensure secure communication.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAlthough this property is optional, heimdall enforces its usage by default. This enforcement can be disabled (not recommended) by starting Heimdall with the \u003ccode\u003e--insecure-skip-ingress-tls-enforcement\u003c/code\u003e flag.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Complex management service configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emanagement\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecure!\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e30s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuffer_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e4KB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10KB\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Services"],"tags":null,"title":"Management Service","url":"/docs/services/management/"},{"categories":null,"content":" As described in Concepts section, mechanisms must be defined and configured before these can be used in rules. That is happening in the so-called mechanisms catalogue. On start up heimdall instantiates all defined and configured mechanisms and makes these available for usage in rules.\nCatalogue Configuration The corresponding mechanisms catalogue resides under the mechanisms property of heimdall static configuration and is organized based on mechanism categories as also shown in the snippet below.\nmechanisms: authenticators: \u0026lt;list of authenticator definitions\u0026gt; authorizers: \u0026lt;list of authorizer definitions\u0026gt; contextualizers: \u0026lt;list of contextualizer definitions\u0026gt; finalizers: \u0026lt;list of finalizer definitions\u0026gt; error_handlers: \u0026lt;list of error handler definitions\u0026gt; General Mechanism Configuration Each mechanism definition entry in the catalogue contains the following properties:\nid - A mandatory unique identifier of the mechanism. Identifiers are used to reference the required mechanism within a rule, respectively its pipelines. You can choose whatever identifier, you want. It is just a name. It must however be unique across all defined mechanisms of a particular mechanism category (like authenticator, authorizer, etc.).\ntype - The mandatory specific type of the mechanism in the given category.\nconfig - The mechanism’s specific configuration if required by the type.\nEvery mechanism type can be configured as many times as needed. However, for those, which don’t have a configuration, it doesn’t really make sense, as all of them would behave the same way.\nFor example, your authenticator definitions could look like this:\nmechanisms: authenticators: - id: anon1 type: anonymous - id: anon2 type: anonymous - id: anon3 type: anonymous config: subject: anon - id: anon4 type: anonymous config: subject: bla The above snippet configures four different instances of the anonymous authenticator mechanism, with anon1 and anon2 being configured identically (as no configuration is provided), and anon3 and anon4 being different in their configuration. Since the first two mentioned behave the same way (both will set the Subject ID to anonymous), there is actually no need to define two instances of them.\nExample Here is an example which defines a mechanism catalogue using some of the available types:\nmechanisms: authenticators: - id: anon_authn type: anonymous - id: opaque_auth_token_authn type: oauth2_introspection config: introspection_endpoint: url: https://hydra:4445/oauth2/introspect assertions: issuers: - https://127.0.0.1:4444/ authorizers: - id: deny_all_authz type: deny - id: local_authz type: cel config: expressions: - expression: \u0026#34;manager\u0026#34; in Subject.Attributes.groups message: user is not in the expected group contextualizers: - id: group_manager type: generic config: endpoint: url: https://group-manager.local/groups method: GET forward_headers: - Authorization cache_ttl: 1m finalizers: - id: jwt_finalizer type: jwt config: signer: key_store: path: /etc/heimdall/signer.pem ttl: 5m claims: | { {{ $user_name := .Subject.Attributes.identity.user_name -}} \u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.identity.email }}, \u0026#34;email_verified\u0026#34;: {{ .Subject.Attributes.identity.email_verified }}, {{ if $user_name -}} \u0026#34;name\u0026#34;: {{ quote $user_name }} {{ else -}} \u0026#34;name\u0026#34;: {{ quote $email }} {{ end -}} } error_handlers: - id: default type: default - id: authenticate_with_kratos type: redirect config: to: https://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }} ","description":"Defines and configures those mechanisms, which should be available for usage in rules.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs described in \u003ca href=\"/docs/concepts/mechanisms/\"\u003eConcepts\u003c/a\u003e section, mechanisms must be defined and configured before these can be used in rules. That is happening in the so-called mechanisms catalogue. On start up heimdall instantiates all defined and configured mechanisms and makes these available for usage in rules.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_catalogue_configuration\"\u003eCatalogue Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe corresponding mechanisms catalogue resides under the \u003ccode\u003emechanisms\u003c/code\u003e property of heimdall static configuration and is organized based on mechanism categories as also shown in the snippet below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026lt;list of authenticator definitions\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026lt;list of authorizer definitions\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtextualizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026lt;list of contextualizer definitions\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026lt;list of finalizer definitions\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eerror_handlers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026lt;list of error handler definitions\u0026gt;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_general_mechanism_configuration\"\u003eGeneral Mechanism Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach mechanism definition entry in the catalogue contains the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eid\u003c/code\u003e - A mandatory unique identifier of the mechanism. Identifiers are used to reference the required mechanism within a rule, respectively its pipelines. You can choose whatever identifier, you want. It is just a name. It must however be unique across all defined mechanisms of a particular mechanism category (like authenticator, authorizer, etc.).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e - The mandatory specific type of the mechanism in the given category.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003econfig\u003c/code\u003e - The mechanism’s specific configuration if required by the type.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEvery mechanism type can be configured as many times as needed. However, for those, which don’t have a configuration, it doesn’t really make sense, as all of them would behave the same way.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor example, your authenticator definitions could look like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon1\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon2\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon3\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon4\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe above snippet configures four different instances of the anonymous authenticator mechanism, with \u003ccode\u003eanon1\u003c/code\u003e and \u003ccode\u003eanon2\u003c/code\u003e being configured identically (as no configuration is provided), and \u003ccode\u003eanon3\u003c/code\u003e and \u003ccode\u003eanon4\u003c/code\u003e being different in their configuration. Since the first two mentioned behave the same way (both will set the Subject ID to \u003ccode\u003eanonymous\u003c/code\u003e), there is actually no need to define two instances of them.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_example\"\u003eExample\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere is an example which defines a mechanism catalogue using some of the available types:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon_authn\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopaque_auth_token_authn\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_introspection\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eintrospection_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://hydra:4445/oauth2/introspect\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4444/\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003elocal_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003emanager\u0026#34;\u003c/span\u003e \u003cspan class=\"s\"\u003ein Subject.Attributes.groups\u003c/span\u003e\n \u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003euser is not in the expected group\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtextualizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egroup_manager\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://group-manager.local/groups\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1m\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_finalizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/signer.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclaims\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ $user_name := .Subject.Attributes.identity.user_name -}}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.identity.email }},\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;email_verified\u0026#34;: {{ .Subject.Attributes.identity.email_verified }},\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ if $user_name -}}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;name\u0026#34;: {{ quote $user_name }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ else -}}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;name\u0026#34;: {{ quote $email }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ end -}}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eerror_handlers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticate_with_kratos\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Catalogue","url":"/docs/mechanisms/catalogue/"},{"categories":null,"content":" E.g. in one case, you want to have access to a particular request header. In another case you would like to add specific data to the resulting JWT created by heimdall. And in yet another case, you may want to check whether some expectations apply. These capabilities are described on this page.\nObjects Objects represent state in the execution of a particular rule. These are the entities, either created or used by particular mechanisms and can represent things, like the actual request, the authenticated subject of the request and many more.\nSubject This object is created by an authenticator which was able to verify the authentication claim available in the request, and contains the information about the authenticated subject. It has the following properties:\nID: string\nThe identifier of the subject.\nAttributes: map\nContains all attributes, which are known about the subject.\nEach object of this type can be thought as a JSON object. Here some examples:\nExample 1. Subject created by an Anonymous Authenticator Subject = { ID: \u0026#34;anonymous\u0026#34;, Attributes: {} } Example 2. Possible Subject created by an OAuth2 Authenticator Subject = { ID: \u0026#34;foobar\u0026#34;, Attributes: { \u0026#34;sub\u0026#34;: \u0026#34;foobar\u0026#34;, \u0026#34;exp\u0026#34;: \u0026#34;1670600805\u0026#34;, \u0026#34;jti\u0026#34;: \u0026#34;7b91ed8a-0251-4e02-8d51-9792785851e8\u0026#34;, \u0026#34;iat\u0026#34;: \u0026#34;1670600305\u0026#34;, \u0026#34;iss\u0026#34;: \u0026#34;https://testauthserver.local\u0026#34;, \u0026#34;nbf\u0026#34;: \u0026#34;1670600305\u0026#34;, \u0026#34;extra\u0026#34;: { \u0026#34;foo\u0026#34;: [\u0026#34;bar\u0026#34;, \u0026#34;baz\u0026#34;] } } } Request This object contains information about the request handled by heimdall and has the following attributes and methods:\nMethod: string\nThe HTTP method used, like GET, POST, etc.\nURL: URL\nThe URL of the matched request. This object has the following properties and methods:\nCaptures: map\nAllows accessing of the values captured by the named wildcards used in the matching path expression of the rule.\nHost: string\nThe host part of the url.\nHostname(): method\nThis method returns the host name stripping any valid port number if present.\nPort(): method\nReturns the port part of the Host, without the leading colon. If Host doesn’t contain a valid numeric port, returns an empty string.\nPath: string\nThe path part of the url.\nQuery(): method\nThe parsed query with each key-value pair being a string to array of strings mapping.\nRawQuery: string\nThe raw query part of the url.\nScheme: string\nThe HTTP scheme part of the url.\nString(): method\nThis method returns the URL as valid URL string of a form scheme:host/path?query.\nClientIPAddresses: string array\nThe list of IP addresses the request passed through with the first entry being the ultimate client of the request. Only available if heimdall is configured to trust the client, sending this information, e.g. in the X-Forwarded-From header (see also trusted_proxies configuration for more details).\nHeader(name): method,\nThis method expects the name of a header as input and returns its value as a string. If the header is not present in the HTTP request an empty string (\u0026#34;\u0026#34;) is returned. If a header appears multiple times in the request, the returned string is a comma separated list of all values.\nA single header may be a comma separated list of actual values as well. Best example is the Accept header, which might be set to e.g. text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8). Cookie(name): method,\nThis method expects the name of a cookie as input and returns the value of it as string. If the cookie is not present in the HTTP request an empty string (\u0026#34;\u0026#34;) is returned.\nBody(): method,\nThe parsed body with contents depending on the Content-Type header. Supported content types are any MIME types with json or yaml subtype, as well as application/x-www-form-urlencoded. If MIME type is unsupported, the method returns a string with the actual body contents.\nThe actual request body is parsed only on the first use of this function. All subsequent calls return the cached result. Example 3. Example results If the Content-Type header is set to application/json and the actual request body is a valid JSON object, shown below\n{ \u0026#34;context\u0026#34;: \u0026#34;heimdall\u0026#34; } The call to the Body() function will return exactly this representation as a map.\nIf the Content-Type header is set to application/yaml and the actual request body is a valid YAML object, shown below\ncontext: heimdall The call to the Body() function will return { \u0026#34;context\u0026#34;: \u0026#34;heimdall\u0026#34; } representation as a map.\nIf the Content-Type header is set to application/x-www-form-urlencoded and the actual request body is a valid object, shown below\ncontext=heimdall The call to the Body() function will return this representation as a map with each value being a string array. In this particular case as { \u0026#34;context\u0026#34;: [ \u0026#34;heimdall\u0026#34; ] }.\nHere is an example for a request object:\nExample 4. Example request object Request = { Method: \u0026#34;GET\u0026#34;, Url: { Scheme: \u0026#34;https\u0026#34;, Host: \u0026#34;localhost\u0026#34;, Path: \u0026#34;/test/abc\u0026#34;, RawQuery: \u0026#34;baz=zab\u0026amp;baz=bar\u0026amp;foo=bar\u0026#34;, Captures: { \u0026#34;value\u0026#34;: \u0026#34;abc\u0026#34; } }, ClientIP: [\u0026#34;127.0.0.1\u0026#34;, \u0026#34;10.10.10.10\u0026#34;] } Outputs This object represents a pipeline execution specific key value map. It is used by pipeline steps to store or read results of particular step executions. Mechanism id used by a pipeline step is used as a key and the value is the corresponding result.\nExample:\nOutputs = { \u0026#34;id_1\u0026#34;: [\u0026#34;a\u0026#34;, \u0026#34;b\u0026#34;], \u0026#34;id_2\u0026#34;: { \u0026#34;foo\u0026#34;: \u0026#34;bar\u0026#34;, \u0026#34;baz\u0026#34;: false } } Payload This object represents the contents of a payload, like the request body or a response body. The contents depend on the MIME-Type of the payload. For json, yaml or x-www-form-urlencoded encoded payload, the object is transformed to a JSON object. Otherwise, it is just a string.\nHere some examples:\nExample 5. Structured payload The following JSON object is a typical response from OPA.\nPayload = { \u0026#34;result\u0026#34;: true } Example 6. Unstructured payload Payload = \u0026#34;SomeStringValue\u0026#34; Error This object represents an error, which has been raised during the execution of a rule and is available in if CEL expressions of Error Handlers. Following properties are available:\nSource: string\nThe ID of the mechanism, which raised the error.\nProper error handling requires attention to the actual error type available via type(Error).\nValues This object represents a key value map, with both, the key and the value being of string type. Though, the actual values can be templated (see (Templating). The contents and the variables available in templates depend on the configuration of the particular mechanism, respectively the corresponding override in a rule.\nHere is an example:\nExample 7. Example values object Values = { \u0026#34;some-key-1\u0026#34;: \u0026#34;value-1\u0026#34;, \u0026#34;some-key-2\u0026#34;: \u0026#34;value-2\u0026#34; } Templating Some mechanisms support templating using Golang Text Templates. Templates can act on all objects described above (Subject, Outputs, Request, Payload and Values). Which exactly are supported is mechanism specific.\nTo ease the usage, all sprig functions, except env and expandenv, as well as the following functions are available:\nurlenc - Encodes a given string using url encoding. Is handy if you need to generate request body or query parameters e.g. for communication with further systems.\natIndex - Implements python-like access to arrays and takes as a single argument the index to access the element in the array at. With index being a positive values it works exactly the same way, as with the usage of the build-in index function to access array elements. With negative index value, one can access the array elements from the tail of the array. -1 is the index of the last element, -2 the index of the element before the last one, etc.\nExample: {{ atIndex 2 [1,2,3,4,5] }} evaluates to 3 (behaves the same way as the index function) and {{ atIndex -2 [1,2,3,4,5] }} evaluates to 4.\nsplitList - Splits a given string using a separator (part of the sprig library, but not documented). The result is a string array.\nExample: {{ splitList \u0026#34;/\u0026#34; \u0026#34;/foo/bar\u0026#34; }} evaluates to the [\u0026#34;\u0026#34;, \u0026#34;foo\u0026#34;, \u0026#34;bar\u0026#34;] array.\nExample 8. Rendering a JSON object Imagine, we have a POST request for the URL https://foobar.baz/zab?foo=bar, with a header X-Foo set to bar value, for which heimdall was able to identify a subject, with ID=foo and which Attributes contain an entry email: foo@bar, then you can generate a JSON object with this information with the following template:\n{ \u0026#34;subject_id\u0026#34;: {{ quote .Subject.ID }}, \u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.email }}, \u0026#34;request_url\u0026#34;: {{ quote .Request.URL }}, \u0026#34;foo_value\u0026#34;: {{ index .Request.URL.Query.foo 0 | quote }} \u0026#34;request_method\u0026#34;: {{ quote .Request.Method }}, \u0026#34;x_foo_value\u0026#34;: {{ .Request.Header \u0026#34;X-Foo\u0026#34; | quote }}, \u0026#34;whatever\u0026#34;: {{ .Outputs.whatever | quote }} } Please note how the access to the foo query parameter is done. Since .Request.URL.Query.foo returns an array of strings, the first element is taken to render the value for the foo_value key.\nThis will result in the following JSON object:\n{ \u0026#34;subject_id\u0026#34;: \u0026#34;foo\u0026#34;, \u0026#34;email\u0026#34;: \u0026#34;foo@bar.baz\u0026#34;, \u0026#34;request_url\u0026#34;: \u0026#34;https://foobar.baz/zab?foo=bar\u0026#34;, \u0026#34;foo_value\u0026#34;: \u0026#34;bar\u0026#34;, \u0026#34;request_method\u0026#34;: \u0026#34;POST\u0026#34;, \u0026#34;x_foo_value\u0026#34;: \u0026#34;bar\u0026#34;, \u0026#34;whatever\u0026#34;: \u0026#34;some value\u0026#34; } Example 9. Access to captured path segments Imagine, we have a POST request to the URL https://foobar.baz/zab/1234, with 1234 being the identifier of a file, which should be updated with the contents sent in the body of the request, and you would like to control access to the aforesaid object using e.g. OpenFGA. This can be achieved with the following authorizer:\nid: openfga_authorizer type: remote config: endpoint: url: https://openfga/stores/files/check payload: | { \u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;, \u0026#34;relation\u0026#34;: \u0026#34;write\u0026#34;, \u0026#34;object\u0026#34;: \u0026#34;file:{{ .Request.URL.Captures.id }}\u0026#34; } expressions: - expression: | Payload.allowed == true Please note how the \u0026#34;object\u0026#34; is set in the payload property above. When the payload template is rendered and for the above said request heimdall was able to identify the subject with ID=foo, following JSON object will be created:\n{ \u0026#34;user\u0026#34;: \u0026#34;user:foo\u0026#34;, \u0026#34;relation\u0026#34;: \u0026#34;write\u0026#34;, \u0026#34;object\u0026#34;: \u0026#34;file:1234\u0026#34; } You can find further examples as part of mechanism descriptions, supporting templating.\nExpressions Expressions can be used to execute conditional logic. As of today only CEL is supported as expression language. All standard, as well as extension functions are available. Which of the evaluation objects are available to the expression depends on the mechanism.\nIn addition to the build-in, respectively extension methods and functions, as well as the methods available on the evaluation objects, following functions are available as well:\nsplit - this function works on strings and expects a separator as a single argument. The result is a string array.\nExample: \u0026#34;/foo/bar/baz\u0026#34;.split(\u0026#34;/\u0026#34;) returns [\u0026#34;\u0026#34;, \u0026#34;foo\u0026#34;, \u0026#34;bar\u0026#34;, \u0026#34;baz\u0026#34;].\nregexFind - this function returns the first (left most) match of a regular expression in the given string.\nExample: \u0026#34;abcd1234\u0026#34;.regexFind(\u0026#34;[a-zA-Z][1-9]\u0026#34;) returns \u0026#34;d1\u0026#34;.\nregexFindAll - this function returns an array of all matches of a regular expression in the given string.\nExample: \u0026#34;123456789\u0026#34;.regexFindAll(\u0026#34;[2,4,6,8]\u0026#34;) returns [\u0026#34;2\u0026#34;,\u0026#34;4\u0026#34;,\u0026#34;6\u0026#34;,\u0026#34;8\u0026#34;].\nat - this function implements python-like access to arrays and takes as a single argument the index to access the element in the array at. With index being a positive values it works exactly the same way, as with the usage of [] to access array elements. With negative index value, one can access the array elements from the tail of the array. -1 is the index of the last element, -2 the index of the element before the last one, etc.\nExample: [1,2,3,4,5].at(2) returns 3 and [1,2,3,4,5].at(-2) returns 4.\nlast - this function works on arrays and returns the last element of an array or nil if the array is empty.\nExample: [1,2,3,4,5].last() returns 5\nSome examples:\nExample 10. Evaluate Payload object Given the following Payload object\nPayload = { \u0026#34;result\u0026#34;: true } a CEL expression to check whether the result attribute is set to true, would look as follows:\nPayload.result == true Example 11. Check whether the user is member of the admin group has(Subject.Attributes.groups) \u0026amp;\u0026amp; Subject.Attributes.groups.exists(g, g == \u0026#34;admin\u0026#34;) Example 12. Access the last path part of the matched URL Request.URL.Path.split(\u0026#34;/\u0026#34;).last() Example 13. Check if an error has been raised by an authenticator with the ID \u0026#34;foo\u0026#34; type(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;foo\u0026#34; ","description":"The dynamic nature of mechanisms is given by the ability to work on different objects and making use of templates and expressions to implement different use cases.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g. in one case, you want to have access to a particular request header. In another case you would like to add specific data to the resulting JWT created by heimdall. And in yet another case, you may want to check whether some expectations apply. These capabilities are described on this page.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_objects\"\u003eObjects\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eObjects represent state in the execution of a particular rule. These are the entities, either created or used by particular mechanisms and can represent things, like the actual request, the authenticated subject of the request and many more.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_subject\"\u003eSubject\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object is created by an authenticator which was able to verify the authentication claim available in the request, and contains the information about the authenticated subject. It has the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eID\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe identifier of the subject.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eAttributes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emap\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eContains all attributes, which are known about the subject.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach object of this type can be thought as a JSON object. Here some examples:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Subject created by an Anonymous Authenticator\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003eSubject\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"na\"\u003eID\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eanonymous\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eAttributes\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Possible Subject created by an OAuth2 Authenticator\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003eSubject\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"na\"\u003eID\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003efoobar\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eAttributes\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003esub\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003efoobar\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eexp\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e1670600805\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ejti\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e7b91ed8a-0251-4e02-8d51-9792785851e8\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eiat\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e1670600305\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eiss\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ehttps://testauthserver.local\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003enbf\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e1670600305\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eextra\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003efoo\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ebar\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ebaz\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_request\"\u003eRequest\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object contains information about the request handled by heimdall and has the following attributes and methods:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eMethod\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe HTTP method used, like \u003ccode\u003eGET\u003c/code\u003e, \u003ccode\u003ePOST\u003c/code\u003e, etc.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_url_captures\" class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eURL\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eURL\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe URL of the matched request. This object has the following properties and methods:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eCaptures\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emap\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAllows accessing of the values captured by the named wildcards used in the matching path expression of the rule.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eHost\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe host part of the url.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eHostname()\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis method returns the host name stripping any valid port number if present.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ePort()\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eReturns the port part of the \u003ccode\u003eHost\u003c/code\u003e, without the leading colon. If \u003ccode\u003eHost\u003c/code\u003e doesn’t contain a valid numeric port, returns an empty string.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ePath\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe path part of the url.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eQuery()\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe parsed query with each key-value pair being a string to array of strings mapping.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eRawQuery\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe raw query part of the url.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eScheme\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe HTTP scheme part of the url.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eString()\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis method returns the URL as valid URL string of a form \u003ccode\u003escheme:host/path?query\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eClientIPAddresses\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe list of IP addresses the request passed through with the first entry being the ultimate client of the request. Only available if heimdall is configured to trust the client, sending this information, e.g. in the \u003ccode\u003eX-Forwarded-From\u003c/code\u003e header (see also \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003etrusted_proxies\u003c/a\u003e configuration for more details).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eHeader(name)\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e,\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis method expects the name of a header as input and returns its value as a \u003ccode\u003estring\u003c/code\u003e. If the header is not present in the HTTP request an empty string (\u003ccode\u003e\u0026#34;\u0026#34;\u003c/code\u003e) is returned. If a header appears multiple times in the request, the returned \u003ccode\u003estring\u003c/code\u003e is a comma separated list of all values.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nA single header may be a comma separated list of actual values as well. Best example is the \u003ccode\u003eAccept\u003c/code\u003e header, which might be set to e.g. \u003ccode\u003etext/html,application/xhtml+xml,application/xml;q=0.9,\u003cstrong\u003e/\u003c/strong\u003e;q=0.8\u003c/code\u003e).\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eCookie(name)\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e,\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis method expects the name of a cookie as input and returns the value of it as \u003ccode\u003estring\u003c/code\u003e. If the cookie is not present in the HTTP request an empty string (\u003ccode\u003e\u0026#34;\u0026#34;\u003c/code\u003e) is returned.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eBody()\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e,\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe parsed body with contents depending on the \u003ccode\u003eContent-Type\u003c/code\u003e header. Supported content types are any MIME types with \u003ccode\u003ejson\u003c/code\u003e or \u003ccode\u003eyaml\u003c/code\u003e subtype, as well as \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e. If MIME type is unsupported, the method returns a string with the actual body contents.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe actual request body is parsed only on the first use of this function. All subsequent calls return the cached result.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Example results\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003eContent-Type\u003c/code\u003e header is set to \u003ccode\u003eapplication/json\u003c/code\u003e and the actual request body is a valid JSON object, shown below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;context\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;heimdall\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe call to the \u003ccode\u003eBody()\u003c/code\u003e function will return exactly this representation as a map.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003eContent-Type\u003c/code\u003e header is set to \u003ccode\u003eapplication/yaml\u003c/code\u003e and the actual request body is a valid YAML object, shown below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003econtext\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe call to the \u003ccode\u003eBody()\u003c/code\u003e function will return \u003ccode\u003e{ \u0026#34;context\u0026#34;: \u0026#34;heimdall\u0026#34; }\u003c/code\u003e representation as a map.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003eContent-Type\u003c/code\u003e header is set to \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e and the actual request body is a valid object, shown below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"s\"\u003econtext=heimdall\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe call to the \u003ccode\u003eBody()\u003c/code\u003e function will return this representation as a map with each value being a string array. In this particular case as \u003ccode\u003e{ \u0026#34;context\u0026#34;: [ \u0026#34;heimdall\u0026#34; ] }\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere is an example for a request object:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Example request object\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003eRequest\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"na\"\u003eMethod\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eGET\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eUrl\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"na\"\u003eScheme\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ehttps\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eHost\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003elocalhost\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003ePath\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e/test/abc\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eRawQuery\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ebaz=zab\u0026amp;baz=bar\u0026amp;foo=bar\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eCaptures\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003evalue\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eabc\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n \u003cspan class=\"na\"\u003eClientIP\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e127.0.0.1\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e10.10.10.10\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_outputs\"\u003eOutputs\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object represents a pipeline execution specific key value map. It is used by pipeline steps to store or read results of particular step executions. Mechanism id used by a pipeline step is used as a key and the value is the corresponding result.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003eOutputs\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eid_1\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ea\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eb\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eid_2\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003efoo\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ebar\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ebaz\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_payload\"\u003ePayload\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object represents the contents of a payload, like the request body or a response body. The contents depend on the MIME-Type of the payload. For \u003ccode\u003ejson\u003c/code\u003e, \u003ccode\u003eyaml\u003c/code\u003e or \u003ccode\u003ex-www-form-urlencoded\u003c/code\u003e encoded payload, the object is transformed to a JSON object. Otherwise, it is just a string.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere some examples:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Structured payload\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following JSON object is a typical response from OPA.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003ePayload\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eresult\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 6. Unstructured payload\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003ePayload\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eSomeStringValue\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_error\"\u003eError\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object represents an error, which has been raised during the execution of a rule and is available in \u003ccode\u003eif\u003c/code\u003e \u003ca href=\"#_expressions\"\u003eCEL expressions\u003c/a\u003e of \u003ca href=\"/docs/mechanisms/error_handlers/\"\u003eError Handlers\u003c/a\u003e. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eSource\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe ID of the mechanism, which raised the error.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eProper error handling requires attention to the actual \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_errorstate_type\"\u003eerror type\u003c/a\u003e\u003c/em\u003e available via \u003ccode\u003etype(Error)\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_values\"\u003eValues\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object represents a key value map, with both, the key and the value being of string type. Though, the actual values can be templated (see (\u003ca href=\"#_templating\"\u003eTemplating\u003c/a\u003e). The contents and the variables available in templates depend on the configuration of the particular mechanism, respectively the corresponding override in a rule.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere is an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 7. Example values object\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003eValues\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003esome-key-1\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003evalue-1\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003esome-key-2\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003evalue-2\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_templating\"\u003eTemplating\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome mechanisms support templating using \u003ca href=\"https://golang.org/pkg/text/template/\"\u003eGolang Text Templates\u003c/a\u003e. Templates can act on all objects described above (\u003ca href=\"#_subject\"\u003eSubject\u003c/a\u003e, \u003ca href=\"#_outputs\"\u003eOutputs\u003c/a\u003e, \u003ca href=\"#_request\"\u003eRequest\u003c/a\u003e, \u003ca href=\"#_payload\"\u003ePayload\u003c/a\u003e and \u003ca href=\"#_values\"\u003eValues\u003c/a\u003e). Which exactly are supported is mechanism specific.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo ease the usage, all \u003ca href=\"https://masterminds.github.io/sprig/\"\u003esprig\u003c/a\u003e functions, except \u003ccode\u003eenv\u003c/code\u003e and \u003ccode\u003eexpandenv\u003c/code\u003e, as well as the following functions are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eurlenc\u003c/code\u003e - Encodes a given string using url encoding. Is handy if you need to generate request body or query parameters e.g. for communication with further systems.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eatIndex\u003c/code\u003e - Implements python-like access to arrays and takes as a single argument the index to access the element in the array at. With index being a positive values it works exactly the same way, as with the usage of the build-in index function to access array elements. With negative index value, one can access the array elements from the tail of the array. -1 is the index of the last element, -2 the index of the element before the last one, etc.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e{{ atIndex 2 [1,2,3,4,5] }}\u003c/code\u003e evaluates to \u003ccode\u003e3\u003c/code\u003e (behaves the same way as the \u003ccode\u003eindex\u003c/code\u003e function) and \u003ccode\u003e{{ atIndex -2 [1,2,3,4,5] }}\u003c/code\u003e evaluates to \u003ccode\u003e4\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003esplitList\u003c/code\u003e - Splits a given string using a separator (part of the sprig library, but not documented). The result is a string array.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e{{ splitList \u0026#34;/\u0026#34; \u0026#34;/foo/bar\u0026#34; }}\u003c/code\u003e evaluates to the \u003ccode\u003e[\u0026#34;\u0026#34;, \u0026#34;foo\u0026#34;, \u0026#34;bar\u0026#34;]\u003c/code\u003e array.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 8. Rendering a JSON object\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine, we have a \u003ccode\u003ePOST\u003c/code\u003e request for the URL \u003ccode\u003ehttps://foobar.baz/zab?foo=bar\u003c/code\u003e, with a header \u003ccode\u003eX-Foo\u003c/code\u003e set to \u003ccode\u003ebar\u003c/code\u003e value, for which heimdall was able to identify a subject, with \u003ccode\u003eID=foo\u003c/code\u003e and which \u003ccode\u003eAttributes\u003c/code\u003e contain an entry \u003ccode\u003eemail: foo@bar\u003c/code\u003e, then you can generate a JSON object with this information with the following template:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"gotemplate\"\u003e{\n \u0026#34;subject_id\u0026#34;: {{ quote .Subject.ID }},\n \u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.email }},\n \u0026#34;request_url\u0026#34;: {{ quote .Request.URL }},\n \u0026#34;foo_value\u0026#34;: {{ index .Request.URL.Query.foo 0 | quote }}\n \u0026#34;request_method\u0026#34;: {{ quote .Request.Method }},\n \u0026#34;x_foo_value\u0026#34;: {{ .Request.Header \u0026#34;X-Foo\u0026#34; | quote }},\n \u0026#34;whatever\u0026#34;: {{ .Outputs.whatever | quote }}\n}\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePlease note how the access to the \u003ccode\u003efoo\u003c/code\u003e query parameter is done. Since \u003ccode\u003e.Request.URL.Query.foo\u003c/code\u003e returns an array of strings, the first element is taken to render the value for the \u003ccode\u003efoo_value\u003c/code\u003e key.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis will result in the following JSON object:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;subject_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;foo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;foo@bar.baz\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;request_url\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://foobar.baz/zab?foo=bar\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;foo_value\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;bar\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;request_method\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;POST\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;x_foo_value\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;bar\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;whatever\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;some value\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 9. Access to captured path segments\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine, we have a \u003ccode\u003ePOST\u003c/code\u003e request to the URL \u003ccode\u003ehttps://foobar.baz/zab/1234\u003c/code\u003e, with \u003ccode\u003e1234\u003c/code\u003e being the identifier of a file, which should be updated with the contents sent in the body of the request, and you would like to control access to the aforesaid object using e.g. OpenFGA. This can be achieved with the following authorizer:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_authorizer\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://openfga/stores/files/check\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;relation\u0026#34;: \u0026#34;write\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;object\u0026#34;: \u0026#34;file:{{ .Request.URL.Captures.id }}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.allowed == true\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePlease note how the \u003ccode\u003e\u0026#34;object\u0026#34;\u003c/code\u003e is set in the \u003ccode\u003epayload\u003c/code\u003e property above. When the \u003ccode\u003epayload\u003c/code\u003e template is rendered and for the above said request heimdall was able to identify the subject with \u003ccode\u003eID=foo\u003c/code\u003e, following JSON object will be created:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;user\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;user:foo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;relation\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;write\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;object\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;file:1234\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can find further examples as part of mechanism descriptions, supporting templating.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_expressions\"\u003eExpressions\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExpressions can be used to execute conditional logic. As of today only \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e is supported as expression language. All standard, as well as \u003ca href=\"https://pkg.go.dev/github.com/google/cel-go/ext#pkg-functions\"\u003eextension\u003c/a\u003e functions are available. Which of the \u003ca href=\"#_objects\"\u003eevaluation objects\u003c/a\u003e are available to the expression depends on the mechanism.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition to the build-in, respectively extension methods and functions, as well as the methods available on the evaluation objects, following functions are available as well:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003esplit\u003c/code\u003e - this function works on strings and expects a separator as a single argument. The result is a string array.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e\u0026#34;/foo/bar/baz\u0026#34;.split(\u0026#34;/\u0026#34;)\u003c/code\u003e returns \u003ccode\u003e[\u0026#34;\u0026#34;, \u0026#34;foo\u0026#34;, \u0026#34;bar\u0026#34;, \u0026#34;baz\u0026#34;]\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eregexFind\u003c/code\u003e - this function returns the first (left most) match of a regular expression in the given string.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e\u0026#34;abcd1234\u0026#34;.regexFind(\u0026#34;[a-zA-Z][1-9]\u0026#34;)\u003c/code\u003e returns \u003ccode\u003e\u0026#34;d1\u0026#34;\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eregexFindAll\u003c/code\u003e - this function returns an array of all matches of a regular expression in the given string.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e\u0026#34;123456789\u0026#34;.regexFindAll(\u0026#34;[2,4,6,8]\u0026#34;)\u003c/code\u003e returns \u003ccode\u003e[\u0026#34;2\u0026#34;,\u0026#34;4\u0026#34;,\u0026#34;6\u0026#34;,\u0026#34;8\u0026#34;]\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eat\u003c/code\u003e - this function implements python-like access to arrays and takes as a single argument the index to access the element in the array at. With index being a positive values it works exactly the same way, as with the usage of \u003ccode\u003e[]\u003c/code\u003e to access array elements. With negative index value, one can access the array elements from the tail of the array. -1 is the index of the last element, -2 the index of the element before the last one, etc.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e[1,2,3,4,5].at(2)\u003c/code\u003e returns \u003ccode\u003e3\u003c/code\u003e and \u003ccode\u003e[1,2,3,4,5].at(-2)\u003c/code\u003e returns \u003ccode\u003e4\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elast\u003c/code\u003e - this function works on arrays and returns the last element of an array or \u003ccode\u003enil\u003c/code\u003e if the array is empty.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e[1,2,3,4,5].last()\u003c/code\u003e returns \u003ccode\u003e5\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome examples:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 10. Evaluate Payload object\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eGiven the following Payload object\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003ePayload\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eresult\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ea CEL expression to check whether the \u003ccode\u003eresult\u003c/code\u003e attribute is set to \u003ccode\u003etrue\u003c/code\u003e, would look as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"cel\"\u003ePayload.result == true\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 11. Check whether the user is member of the admin group\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"cel\"\u003ehas(Subject.Attributes.groups) \u0026amp;\u0026amp;\n Subject.Attributes.groups.exists(g, g == \u0026#34;admin\u0026#34;)\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 12. Access the last path part of the matched URL\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"cel\"\u003eRequest.URL.Path.split(\u0026#34;/\u0026#34;).last()\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 13. Check if an error has been raised by an authenticator with the ID \u0026#34;foo\u0026#34;\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"cel\"\u003etype(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;foo\u0026#34;\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Objects, Templating \u0026 Co","url":"/docs/mechanisms/evaluation_objects/"},{"categories":null,"content":" Some of the supported authenticator types may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overriddable and partially overridable to indicate whether the property can be overridden in a rule pipeline.\nUnauthorized This authenticator rejects all requests as unauthenticated (on HTTP response code level this is then mapped to 401 Unauthorized, hence the type name). It basically stops the successful execution of the pipeline resulting in the execution of the error handlers. This authenticator type doesn’t have any configuration options.\nTo enable the usage of this authenticator, you have to set the type property to unauthorized.\nExample 1. Configure Unauthorized authenticator id: foo type: unauthorized Anonymous This authenticator just creates a Subject object and sets its ID to anonymous without doing anything else. You can overwrite the value of subject’s id by using the optional config property.\nTo enable the usage of this authenticator, you have to set the type property to anonymous.\nConfiguration using the config property is optional. Following properties are available:\nsubject: string (optional, overridable)\nEnables setting the ID of the created Subject object to a custom value.\nExample 2. Configuration of Anonymous authenticator id: foo type: anonymous config: subject: anon Basic Auth This authenticator verifies the provided credentials according to the HTTP \u0026#34;Basic\u0026#34; authentication scheme, described in RFC 7617. It does however not challenge the authentication, it only verifies the provided credentials and sets the Subject ID to the configured user identifier if the authentication succeeds. Otherwise, it raises an error, resulting in the execution of the configured error handlers. The \u0026#34;WWW Authenticate\u0026#34; error handler mechanism can for example be used if the corresponding challenge is required.\nTo enable the usage of this authenticator, you have to set the type property to basic_auth.\nConfiguration using the config property is mandatory. Following properties are available:\nuser_id: string (mandatory, overridable)\nThe identifier of the subject to be verified.\npassword: string (mandatory, overridable)\nThe password of the subject to be verified.\nallow_fallback_on_error: boolean (optional, overridable)\nIf set to true, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to false.\nExample 3. Configuration of Basic Auth authenticator id: foo type: basic_auth config: user_id: bar password: baz Generic This authenticator is kind of a Swiss knife and can do a lot depending on the given configuration. It verifies the authentication status of the subject by making use of values available in cookies, headers, or query parameters of the HTTP request and communicating with the actual authentication system to perform the verification of the subject authentication status on the one hand, and to get the information about the subject on the other hand. There is however one limitation: it can only deal with JSON responses.\nTo enable the usage of this authenticator, you have to set the type property to generic.\nConfiguration using the config property is mandatory. Following properties are available:\nidentity_info_endpoint: Endpoint (mandatory, not overridable)\nThe endpoint to communicate to for the actual subject authentication status verification purpose. At least the url must be configured. If you don’t configure method, HTTP POST will be used. The Accept header is set to application/json by default. You can overwrite these setting if required. Query and header definitions can be templated and can make use of the AuthenticationData object (see below). Don’t forget - this authenticator supports only JSON responses.\nauthentication_data_source: Authentication Data Source (mandatory, not overridable)\nWhere to extract the authentication data from the request. The extracted value is made available as AuthenticationData for usage in templates defined as part of this authenticator configuration. So you can reference it in a body, header, etc.\nThe AuthenticationData object is available during the execution of this authenticator only and is not made available to other mechanisms. forward_headers: string array (optional, not overridable)\nIf the identity_info_endpoint API requires any headers from the request to heimdall, you can forward these unchanged by making use of this property. This might be the header used to extract the authentication data from.\nforward_cookies: string array (optional, not overridable)\nIf the identity_info_endpoint API requires any cookies from the request to heimdall, you can forward these unchanged by making use of this property. This might be the cookie used to extract the authentication data from.\npayload: string (optional, not overridable)\nYour template with definitions required to send the extracted authentication data. The template has access to the AuthenticationData object only.\nsubject: Subject (mandatory, not overridable)\nWhere to extract the Subject information from the identity info endpoint response.\ncache_ttl: Duration (optional, overridable)\nHow long to cache the response. If not set, response caching if disabled. The cache key is calculated from the identity_info_endpoint configuration and the actual authentication data value.\nallow_fallback_on_error: boolean (optional, overridable)\nIf set to true, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to false.\nsession_lifespan: Session Lifespan (optional, not overridable)\nWhere to extract the session validity information form the identity info endpoint response. If the not_after property is specified, the corresponding value from the response is also used for cache ttl calculation to prevent usage of not anymore valid session objects and overwrites the value configured for cache_ttl if the usage of that value would exceed the lifespan of the session object.\nIf you’re configuring the cache_ttl property, it is highly recommended to configure session_lifespan as well to ensure outdated session objects are not used for subsequent requests to heimdall. Usage of session_lifespan is recommended anyway to enable time based validation of the response from the identity info endpoint. Example 4. Configuration to work with session cookies This example shows how to configure this authenticator to work with Ory Kratos, an authentication system, which issues a cookie upon successful user authentication to maintain the authentication state. To reduce the communication overhead, it also makes use of cache_ttl to cache the response for 5 minutes if that time frame does not exceed the actual validity of the session represented by the cookie.\nid: kratos_session_cookie type: generic config: identity_info_endpoint: https://kratos/sessions/whoami authentication_data_source: - cookie: ory_kratos_session forward_cookies: - ory_kratos_session subject: id: \u0026#34;identity.id\u0026#34; cache_ttl: 5m session_lifespan: active: active issued_at: issued_at not_before: authenticated_at not_after: expires_at time_format: \u0026#34;2006-01-02T15:04:05.999999Z07\u0026#34; validity_leeway: 10s As kratos requires the ory_kratos_session cookie as is, this configuration makes use of the forward_cookies property and does not use the AuthenticationData object.\nThis example does also show how an endpoint can be configured by just specifying the URL as string, which is the simplest way for endpoint configuration.\nExample 5. Configuration to work with a Bearer token This example shows how to configure this authenticator to work with an OAuth2 authorization service, which issues a Bearer token upon successful user authentication. To reduce the communication overhead, it also makes use of cache_ttl to cache the response for 5 minutes if it does not exceed the validity of the information present in the response from the used endpoint.\nIn this example we configure the authenticator to use the introspection endpoint to get the information about the token.\nid: opaque_bearer_token type: generic config: identity_info_endpoint: url: https://my-auth.system/introspect headers: Content-Type: application/x-www-form-urlencoded auth: type: basic_auth config: user: Heimdall password: ${INTROSPECTION_PASSWORD} authentication_data_source: - header: Authorization scheme: Bearer payload: | token={{ urlenc .AuthenticationData }}\u0026amp;token_type_hint=access_token subject: id: sub cache_ttl: 5m session_lifespan: active: active issued_at: iat not_before: nbf not_after: exp validity_leeway: 10s Usually, you would not only like to verify the validity of a token, but also a couple of claims. This can be achieved by a CEL Authorizer. However, there is also a special purpose OAuth2 Introspection authenticator type, which supports asserting all security relevant claims in just one place and does not need so much configuration as shown above.\nIn this configuration the authenticator extracts the token from the Authorization header and request the information about the corresponding user from the https://my-auth.system/introspect endpoint by sending the extracted token in the body of the request in a parameter named token.\nExample 6. Configuration to work with Google’s Firebase. If you would like to integrate with Google’s Firebase, you would configure something like this:\nAssumption: The token issued by firebase is located in the HTTP Authorization header using Bearer scheme\nid: firebase_token type: generic config: identity_info_endpoint: url: https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${YOUR_API_KEY} headers: Content-Type: application/json authentication_data_source: - header: Authorization scheme: Bearer payload: | { \u0026#34;idToken\u0026#34;: {{ quote .AuthenticationData }} } subject: id: users.0.localId attributes: users.0 cache_ttl: 5m OAuth2 Introspection This authenticator handles requests that have Bearer token in the HTTP Authorization header (Authorization: Bearer \u0026lt;token\u0026gt;), in the access_token query parameter or the access_token body parameter (latter, if the body is of application/x-www-form-urlencoded MIME type). It then uses OAuth 2.0 Token Introspection endpoint to check if the token is valid. The validation includes at least the verification of the status and the time validity. That is if the token is still active and whether it has been issued in an acceptable time frame. Latter can be adjusted by specifying a leeway. All other validation options can and should be configured.\nTo enable the usage of this authenticator, you have to set the type property to oauth2_introspection.\nConfiguration using the config property is mandatory. Following properties are available:\nintrospection_endpoint: Endpoint (dependant, not overridable)\nThe OAuth 2.0 Token Introspection endpoint of the OAuth2 authorization provider.\nThe configuration of this property is mutually exclusive with metadata_endpoint. If used, at least the url must be configured. There is no need to define the method property or setting the Content-Type or the Accept header. These are set by default to the values required by the RFC referenced above. You can however override these while configuring the authenticator if needed. The path part of the url can be templated and has access to the TokenIssuer object, which is a string and only available if the format of the used token is JWT. It basically holds the value of the iss claim from the token.\nmetadata_endpoint: Endpoint (dependant, not overridable)\nThe OAuth 2.0 Authorization Server Metadata endpoint of the OAuth2, respectively OIDC authorization provider (the OpenID Connect Discovery specification is an OIDC specific profile of that specification). If the token introspection URL is not known upfront, it can be resolved by making use of that endpoint.\nThe configuration of this property is mutually exclusive with introspection_endpoint. If used, at least the url must be configured, can be templated and has access to the TokenIssuer object already introduced above (with the same limitations).\nThe metadata_endpoint is by default configured to use GET as HTTP method and sets the Accept header to application/json as also required by both specifications referenced above. In addition, to avoid useless communication, it is also configured to make use of HTTP cache according to RFC 7234 with default HTTP cache ttl set to 30m. All these settings can however be overridden if required.\nIn addition to the properties specified by the endpoint type, following properties are available:\ndisable_issuer_identifier_verification: boolean (optional, not overridable)\nUpon retrieval of the server metadata, both, the OAuth 2.0 Authorization Server Metadata RFC, and the OpenID Connect Discovery specification, require the verification of the issuer identifier for security reasons, e.g. to prevent Spoofing Attacks. There are however setups, where strictly following that recommendation would result in extended bandwidth usage (instead of communicating directly with the auth server within the cluster one would need to use the same domain, the client application uses, which introduces additional network hops). It might also not work at all as the actual identifier of the issuer would change depending on where the request come from. By making use of this property and setting it to true, one can disable the corresponding verification. Defaults to false.\ntoken_source: Authentication Data Source (optional, not overridable)\nWhere to get the access token from. Defaults to retrieve it from the Authorization header, the access_token query parameter or the access_token body parameter (latter, if the body is of application/x-www-form-urlencoded MIME type).\nassertions: Assertions (dependent, overridable)\nConfigures the required claim assertions. Overriding on rule level is possible even partially. Those parts of the assertion, which have not been overridden are taken from the prototype configuration. If metadata_endpoint is used, the list of issuers is optional, as the issuer will be resolved via the auth server metadata document. Otherwise, the list of issuers is mandatory.\nsubject: Subject (optional, not overridable)\nWhere to extract the Subject information from the introspection endpoint response. If not configured sub is used to extract the subject ID and all attributes from the introspection endpoint response are made available as Attributes.\ncache_ttl: Duration (optional, overridable)\nHow long to cache the response. If not set, caching of the introspection response is based on the available token expiration information. To disable caching, set it to 0s. If you set the ttl to a custom value \u0026gt; 0, the expiration time (if available) of the token will be considered. The cache key is calculated from the introspection_endpoint configuration and the value of the access token.\nallow_fallback_on_error: boolean (optional, overridable)\nIf set to true, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to false.\nExample 7. Minimal possible configuration based on the Introspection endpoint id: at_opaque type: oauth2_introspection config: introspection_endpoint: url: https://hydra:4445/oauth2/introspect assertions: issuers: - https://127.0.0.1:4444/ Example 8. Configuration for Keycloak utilizing metadata discovery id: keycloak type: metadata_endpoint config: metadata_endpoint: url: https://keycloak:8080/realms/{{ trimPrefix \u0026#34;https://my-auth-server/realms/\u0026#34; .TokenIssuer }}/.well-known/openid-configuration # Note that no assertions are configured here, since it\u0026#39;ll be resolved via the metadata endpoint This example does also show how to make use of templating if the format of the access token is JWT.\nThe external domain of the auth server in this example is https://my-auth-server.com. If the iss claim of the issued JWT is set to https://my-auth-server.com/realms/my-app, the above line will build an internal URL to the metadata endpoint of the same server and profile/realm, which is that case would be https://keycloak:8080/realms/my-app/.well-known/openid-configuration\nJWT As the OAuth2 Introspection authenticator, this authenticator handles requests that have a Bearer token in the Authorization header, in a different header, a query parameter or a body parameter as well. Unlike the OAuth2 Introspection authenticator it expects the token to be a JSON Web Token (JWT) and verifies it according RFC 7519, Section 7.2. It does however not support encrypted payloads and nested JWTs. In addition to this, validation includes the verification of the time validity. Latter can be adjusted by specifying a leeway. All other validation options can and should be configured.\nTo enable the usage of this authenticator, you have to set the type property to jwt.\nConfiguration using the config property is mandatory. Following properties are available:\njwks_endpoint: Endpoint (dependant, not overridable)\nThe JWKS endpoint, this authenticator retrieves the key material in a format specified in RFC 7519 from for JWT signature verification purposes.\nThe configuration of this property is mutually exclusive with metadata_endpoint. If used, at least the url must be configured. By default method is set to GET and the HTTP Accept header to application/json. The path part of the url can be templated and has access to the TokenIssuer object, which is a string and basically holds the value of the iss claim from the token.\nmetadata_endpoint: Endpoint (dependant, not overridable)\nThe OAuth 2.0 Authorization Server Metadata endpoint of the OAuth2, respectively OIDC authorization provider (the OpenID Connect Discovery specification is an OIDC specific profile of that specification). If the JWKS URL is not known upfront, it can be resolved by making use of that endpoint.\nThe configuration of this property is mutually exclusive with jwks_endpoint. If used, at least the url must be configured. As with the jwks_endpoint, the path part of the url can be templated and has access to the TokenIssuer object already introduced above.\nAs with the jwks_endpoint as well, the metadata_endpoint is by default configured to use GET as HTTP method and sets the Accept header to application/json, as also required by both specifications referenced above. In addition, to avoid useless communication, it is also configured to make use of HTTP cache according to RFC 7234 with default HTTP cache ttl set to 30m. All these settings can however be overridden if required.\nIn addition to the properties specified by the endpoint type, following properties are available:\ndisable_issuer_identifier_verification: boolean (optional, not overridable)\nUpon retrieval of the server metadata, both, the OAuth 2.0 Authorization Server Metadata RFC, and the OpenID Connect Discovery specification, require the verification of the issuer identifier for security reasons, e.g. to prevent Spoofing Attacks. There are however setups, where strictly following that recommendation would result in extended bandwidth usage (instead of communicating directly with the auth server within the cluster one would need to use the same domain, the client application uses, which introduces additional network hops). It might also not work at all as the actual identifier of the issuer would change depending on where the request come from. By making use of this property and setting it to true, one can disable the corresponding verification. Defaults to false.\njwt_source: Authentication Data Source (optional, not overridable)\nWhere to get the access token from. Defaults to retrieve it from the Authorization header, the access_token query parameter or the access_token body parameter (latter, if the body is of application/x-www-form-urlencoded MIME type).\nassertions: Assertions (dependant, overridable)\nConfigures the required claim assertions. Overriding on rule level is possible even partially. Those parts of the assertion, which have not been overridden are taken from the prototype configuration. If metadata_endpoint is used, the list of issuers is optional, as the issuer will be resolved via the auth server metadata document. Otherwise, the list of issuers is mandatory.\nsubject: Subject (optional, not overridable)\nWhere to extract the subject id from the JWT, as well as which attributes to use. If not configured sub is used to extract the subject id and all attributes from the JWT payload are made available as attributes of the subject.\ncache_ttl: Duration (optional, overridable)\nHow long to cache the key from the JWKS response, which was used for signature verification purposes. If not set, heimdall will cache this key for 10 minutes and not call JWKS endpoint again if the same kid is referenced in an JWT and same JWKS endpoint is used. The cache key is calculated from the jwks_endpoint configuration and the kid referenced in the JWT.\nallow_fallback_on_error: boolean (optional, overridable)\nIf set to true, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to false.\nvalidate_jwk: boolean (optional, not overridable)\nEnables or disables the verification of the JWK certificate used for JWT signature verification purposes. Effective only if the JWK contains a certificate. The verification happens according to RFC 5280, section 6.1 and also includes the check, that the certificate is allowed to be used for signature verification purposes. Revocation check is not supported. Defaults to true.\ntrust_store: string (optional, not overridable)\nThe path to a PEM file containing the trust anchors, to be used for the JWK certificate validation. Defaults to system trust store.\nIf a JWT does not reference a kid, heimdall always fetches a JWKS from the configured endpoint (so no caching is done) and iterates over the received keys until one matches. If none matches, the authenticator fails. Example 9. Minimal possible configuration based on the JWKS endpoint id: at_jwt type: jwt config: jwks_endpoint: url: https://hydra:4444/.well-known/jwks.json assertions: issuers: - https://127.0.0.1:4444/ Example 10. Configuration for Keycloak utilizing metadata discovery id: keycloak type: jwt config: metadata_endpoint: url: https://keycloak:8080/realms/my-app/.well-known/openid-configuration # Note that no assertions are configured here, since it\u0026#39;ll be resolved via the metadata endpoint ","description":"Authenticators verify the authentication status of requests and create subjects. This page describes the available authenticator types in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome of the supported authenticator types may support or require additional configuration. The corresponding properties are annotated with \u003ccode\u003emandatory\u003c/code\u003e, respectively \u003ccode\u003eoptional\u003c/code\u003e to denote configuration requirement, as well as with \u003ccode\u003eoverridable\u003c/code\u003e, \u003ccode\u003enot overriddable\u003c/code\u003e and \u003ccode\u003epartially overridable\u003c/code\u003e to indicate whether the property can be overridden in a rule pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_unauthorized\"\u003eUnauthorized\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authenticator rejects all requests as unauthenticated (on HTTP response code level this is then mapped to \u003ccode\u003e401 Unauthorized\u003c/code\u003e, hence the type name). It basically stops the successful execution of the pipeline resulting in the execution of the error handlers. This authenticator type doesn’t have any configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eunauthorized\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Configure Unauthorized authenticator\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eunauthorized\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_anonymous\"\u003eAnonymous\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authenticator just creates a \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e object and sets its \u003ccode\u003eID\u003c/code\u003e to \u003ccode\u003eanonymous\u003c/code\u003e without doing anything else. You can overwrite the value of subject’s id by using the optional \u003ccode\u003econfig\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eanonymous\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is optional. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esubject\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables setting the \u003ccode\u003eID\u003c/code\u003e of the created \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e object to a custom value.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Configuration of Anonymous authenticator\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_basic_auth\"\u003eBasic Auth\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authenticator verifies the provided credentials according to the HTTP \u0026#34;Basic\u0026#34; authentication scheme, described in \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7617\"\u003eRFC 7617\u003c/a\u003e. It does however not challenge the authentication, it only verifies the provided credentials and sets the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e \u003ccode\u003eID\u003c/code\u003e to the configured user identifier if the authentication succeeds. Otherwise, it raises an error, resulting in the execution of the configured error handlers. The \u003ca href=\"/docs/mechanisms/error_handlers/#_www_authenticate\"\u003e\u0026#34;WWW Authenticate\u0026#34;\u003c/a\u003e error handler mechanism can for example be used if the corresponding challenge is required.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ebasic_auth\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003euser_id\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe identifier of the subject to be verified.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epassword\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe password of the subject to be verified.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_fallback_on_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf set to \u003ccode\u003etrue\u003c/code\u003e, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Configuration of Basic Auth authenticator\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebaz\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_generic\"\u003eGeneric\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authenticator is kind of a Swiss knife and can do a lot depending on the given configuration. It verifies the authentication status of the subject by making use of values available in cookies, headers, or query parameters of the HTTP request and communicating with the actual authentication system to perform the verification of the subject authentication status on the one hand, and to get the information about the subject on the other hand. There is however one limitation: it can only deal with JSON responses.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003egeneric\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eidentity_info_endpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe endpoint to communicate to for the actual subject authentication status verification purpose. At least the \u003ccode\u003eurl\u003c/code\u003e must be configured. If you don’t configure \u003ccode\u003emethod\u003c/code\u003e, HTTP \u003ccode\u003ePOST\u003c/code\u003e will be used. The \u003ccode\u003eAccept\u003c/code\u003e header is set to \u003ccode\u003eapplication/json\u003c/code\u003e by default. You can overwrite these setting if required. Query and header definitions can be templated and can make use of the \u003ccode\u003eAuthenticationData\u003c/code\u003e object (see below). Don’t forget - this authenticator supports only JSON responses.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauthentication_data_source\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_authentication_data_source\"\u003eAuthentication Data Source\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to extract the authentication data from the request. The extracted value is made available as \u003ccode\u003eAuthenticationData\u003c/code\u003e for usage in templates defined as part of this authenticator configuration. So you can reference it in a body, header, etc.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe \u003ccode\u003eAuthenticationData\u003c/code\u003e object is available during the execution of this authenticator only and is not made available to other mechanisms.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_headers\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003eidentity_info_endpoint\u003c/code\u003e API requires any headers from the request to heimdall, you can forward these unchanged by making use of this property. This might be the header used to extract the authentication data from.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_cookies\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003eidentity_info_endpoint\u003c/code\u003e API requires any cookies from the request to heimdall, you can forward these unchanged by making use of this property. This might be the cookie used to extract the authentication data from.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epayload\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYour \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003etemplate\u003c/a\u003e with definitions required to send the extracted authentication data. The template has access to the \u003ccode\u003eAuthenticationData\u003c/code\u003e object only.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esubject\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_subject\"\u003eSubject\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to extract the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e information from the identity info endpoint response.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow long to cache the response. If not set, response caching if disabled. The cache key is calculated from the \u003ccode\u003eidentity_info_endpoint\u003c/code\u003e configuration and the actual authentication data value.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_fallback_on_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf set to \u003ccode\u003etrue\u003c/code\u003e, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esession_lifespan\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_session_lifespan\"\u003eSession Lifespan\u003c/a\u003e\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to extract the session validity information form the identity info endpoint response. If the \u003ccode\u003enot_after\u003c/code\u003e property is specified, the corresponding value from the response is also used for cache ttl calculation to prevent usage of not anymore valid session objects and overwrites the value configured for \u003ccode\u003ecache_ttl\u003c/code\u003e if the usage of that value would exceed the lifespan of the session object.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you’re configuring the \u003ccode\u003ecache_ttl\u003c/code\u003e property, it is highly recommended to configure \u003ccode\u003esession_lifespan\u003c/code\u003e as well to ensure outdated session objects are not used for subsequent requests to heimdall. Usage of \u003ccode\u003esession_lifespan\u003c/code\u003e is recommended anyway to enable time based validation of the response from the identity info endpoint.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Configuration to work with session cookies\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example shows how to configure this authenticator to work with Ory Kratos, an authentication system, which issues a cookie upon successful user authentication to maintain the authentication state. To reduce the communication overhead, it also makes use of \u003ccode\u003ecache_ttl\u003c/code\u003e to cache the response for 5 minutes if that time frame does not exceed the actual validity of the session represented by the cookie.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekratos_session_cookie\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidentity_info_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://kratos/sessions/whoami\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_data_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ecookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eory_kratos_session\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_cookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eory_kratos_session\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eidentity.id\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003esession_lifespan\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eactive\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eactive\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissued_at\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eissued_at\u003c/span\u003e\n \u003cspan class=\"na\"\u003enot_before\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticated_at\u003c/span\u003e\n \u003cspan class=\"na\"\u003enot_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexpires_at\u003c/span\u003e\n \u003cspan class=\"na\"\u003etime_format\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e2006-01-02T15:04:05.999999Z07\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalidity_leeway\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs kratos requires the \u003ccode\u003eory_kratos_session\u003c/code\u003e cookie as is, this configuration makes use of the \u003ccode\u003eforward_cookies\u003c/code\u003e property and does not use the \u003ccode\u003eAuthenticationData\u003c/code\u003e object.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example does also show how an endpoint can be configured by just specifying the URL as string, which is the simplest way for endpoint configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Configuration to work with a Bearer token\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example shows how to configure this authenticator to work with an OAuth2 authorization service, which issues a Bearer token upon successful user authentication. To reduce the communication overhead, it also makes use of \u003ccode\u003ecache_ttl\u003c/code\u003e to cache the response for 5 minutes if it does not exceed the validity of the information present in the response from the used endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example we configure the authenticator to use the introspection endpoint to get the information about the token.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopaque_bearer_token\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidentity_info_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://my-auth.system/introspect\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eContent-Type\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapplication/x-www-form-urlencoded\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eHeimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${INTROSPECTION_PASSWORD}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_data_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003etoken={{ urlenc .AuthenticationData }}\u0026amp;token_type_hint=access_token\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esub\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003esession_lifespan\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eactive\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eactive\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissued_at\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eiat\u003c/span\u003e\n \u003cspan class=\"na\"\u003enot_before\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enbf\u003c/span\u003e\n \u003cspan class=\"na\"\u003enot_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexp\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalidity_leeway\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUsually, you would not only like to verify the validity of a token, but also a couple of claims. This can be achieved by a \u003ca href=\"/docs/mechanisms/authorizers/#_local_cel\"\u003eCEL Authorizer\u003c/a\u003e. However, there is also a special purpose \u003ca href=\"#_oauth2_introspection\"\u003eOAuth2 Introspection\u003c/a\u003e authenticator type, which supports asserting all security relevant claims in just one place and does not need so much configuration as shown above.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this configuration the authenticator extracts the token from the \u003ccode\u003eAuthorization\u003c/code\u003e header and request the information about the corresponding user from the \u003ccode\u003ehttps://my-auth.system/introspect\u003c/code\u003e endpoint by sending the extracted token in the body of the request in a parameter named \u003ccode\u003etoken\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 6. Configuration to work with Google’s Firebase.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you would like to integrate with Google’s Firebase, you would configure something like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAssumption: The token issued by firebase is located in the HTTP Authorization header using Bearer scheme\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efirebase_token\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidentity_info_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${YOUR_API_KEY}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eContent-Type\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapplication/json\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_data_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{ \u0026#34;idToken\u0026#34;: {{ quote .AuthenticationData }} }\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eusers.0.localId\u003c/span\u003e\n \u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eusers.0\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_oauth2_introspection\"\u003eOAuth2 Introspection\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authenticator handles requests that have Bearer token in the HTTP Authorization header (\u003ccode\u003eAuthorization: Bearer \u0026lt;token\u0026gt;\u003c/code\u003e), in the \u003ccode\u003eaccess_token\u003c/code\u003e query parameter or the \u003ccode\u003eaccess_token\u003c/code\u003e body parameter (latter, if the body is of \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e MIME type). It then uses \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7662\"\u003eOAuth 2.0 Token Introspection\u003c/a\u003e endpoint to check if the token is valid. The validation includes at least the verification of the status and the time validity. That is if the token is still active and whether it has been issued in an acceptable time frame. Latter can be adjusted by specifying a leeway. All other validation options can and should be configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eoauth2_introspection\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eintrospection_endpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (dependant, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7662\"\u003eOAuth 2.0 Token Introspection\u003c/a\u003e endpoint of the OAuth2 authorization provider.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this property is mutually exclusive with \u003ccode\u003emetadata_endpoint\u003c/code\u003e. If used, at least the \u003ccode\u003eurl\u003c/code\u003e must be configured. There is no need to define the \u003ccode\u003emethod\u003c/code\u003e property or setting the \u003ccode\u003eContent-Type\u003c/code\u003e or the \u003ccode\u003eAccept\u003c/code\u003e header. These are set by default to the values required by the RFC referenced above. You can however override these while configuring the authenticator if needed. The path part of the \u003ccode\u003eurl\u003c/code\u003e can be \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003etemplated\u003c/a\u003e and has access to the \u003ccode\u003eTokenIssuer\u003c/code\u003e object, which is a string and only available if the format of the used token is JWT. It basically holds the value of the \u003ccode\u003eiss\u003c/code\u003e claim from the token.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emetadata_endpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (dependant, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414\"\u003eOAuth 2.0 Authorization Server Metadata\u003c/a\u003e endpoint of the OAuth2, respectively OIDC authorization provider (the \u003ca href=\"https://openid.net/specs/openid-connect-discovery-1_0.html\"\u003eOpenID Connect Discovery\u003c/a\u003e specification is an OIDC specific profile of that specification). If the token introspection URL is not known upfront, it can be resolved by making use of that endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this property is mutually exclusive with \u003ccode\u003eintrospection_endpoint\u003c/code\u003e. If used, at least the \u003ccode\u003eurl\u003c/code\u003e must be configured, can be templated and has access to the \u003ccode\u003eTokenIssuer\u003c/code\u003e object already introduced above (with the same limitations).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ccode\u003emetadata_endpoint\u003c/code\u003e is by default configured to use \u003ccode\u003eGET\u003c/code\u003e as HTTP method and sets the \u003ccode\u003eAccept\u003c/code\u003e header to \u003ccode\u003eapplication/json\u003c/code\u003e as also required by both specifications referenced above. In addition, to avoid useless communication, it is also configured to make use of HTTP cache according to \u003ca href=\"https://tools.ietf.org/html/rfc7234\"\u003eRFC 7234\u003c/a\u003e with default HTTP cache ttl set to \u003ccode\u003e30m\u003c/code\u003e. All these settings can however be overridden if required.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition to the properties specified by the \u003ca href=\"/docs/configuration/types/#_endpoint\"\u003e\u003ccode\u003eendpoint\u003c/code\u003e\u003c/a\u003e type, following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edisable_issuer_identifier_verification\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUpon retrieval of the server metadata, both, the \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414\"\u003eOAuth 2.0 Authorization Server Metadata\u003c/a\u003e RFC, and the \u003ca href=\"https://openid.net/specs/openid-connect-discovery-1_0.html\"\u003eOpenID Connect Discovery\u003c/a\u003e specification, require the verification of the issuer identifier for security reasons, e.g. to prevent \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414#section-6.2\"\u003eSpoofing Attacks\u003c/a\u003e. There are however setups, where strictly following that recommendation would result in extended bandwidth usage (instead of communicating directly with the auth server within the cluster one would need to use the same domain, the client application uses, which introduces additional network hops). It might also not work at all as the actual identifier of the issuer would change depending on where the request come from. By making use of this property and setting it to \u003ccode\u003etrue\u003c/code\u003e, one can disable the corresponding verification. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etoken_source\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_authentication_data_source\"\u003eAuthentication Data Source\u003c/a\u003e\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to get the access token from. Defaults to retrieve it from the \u003ccode\u003eAuthorization\u003c/code\u003e header, the \u003ccode\u003eaccess_token\u003c/code\u003e query parameter or the \u003ccode\u003eaccess_token\u003c/code\u003e body parameter (latter, if the body is of \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e MIME type).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eassertions\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_assertions\"\u003eAssertions\u003c/a\u003e\u003c/em\u003e (dependent, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfigures the required claim assertions. Overriding on rule level is possible even partially. Those parts of the assertion, which have not been overridden are taken from the prototype configuration. If \u003ccode\u003emetadata_endpoint\u003c/code\u003e is used, the list of issuers is optional, as the issuer will be resolved via the auth server metadata document. Otherwise, the list of issuers is mandatory.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esubject\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_subject\"\u003eSubject\u003c/a\u003e\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to extract the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e information from the introspection endpoint response. If not configured \u003ccode\u003esub\u003c/code\u003e is used to extract the subject \u003ccode\u003eID\u003c/code\u003e and all attributes from the introspection endpoint response are made available as \u003ccode\u003eAttributes\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow long to cache the response. If not set, caching of the introspection response is based on the available token expiration information. To disable caching, set it to \u003ccode\u003e0s\u003c/code\u003e. If you set the ttl to a custom value \u0026gt; 0, the expiration time (if available) of the token will be considered. The cache key is calculated from the \u003ccode\u003eintrospection_endpoint\u003c/code\u003e configuration and the value of the access token.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_fallback_on_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf set to \u003ccode\u003etrue\u003c/code\u003e, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 7. Minimal possible configuration based on the Introspection endpoint\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eat_opaque\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_introspection\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eintrospection_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://hydra:4445/oauth2/introspect\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4444/\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 8. Configuration for Keycloak utilizing metadata discovery\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emetadata_endpoint\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emetadata_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://keycloak:8080/realms/{{ trimPrefix \u0026#34;https://my-auth-server/realms/\u0026#34; .TokenIssuer }}/.well-known/openid-configuration\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# Note that no assertions are configured here, since it\u0026#39;ll be resolved via the metadata endpoint\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example does also show how to make use of templating if the format of the access token is JWT.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe external domain of the auth server in this example is \u003ccode\u003ehttps://my-auth-server.com\u003c/code\u003e.\nIf the \u003ccode\u003eiss\u003c/code\u003e claim of the issued JWT is set to \u003ccode\u003ehttps://my-auth-server.com/realms/my-app\u003c/code\u003e, the above line will build an internal URL to the metadata endpoint of the same server and profile/realm, which is that case would be \u003ccode\u003ehttps://keycloak:8080/realms/my-app/.well-known/openid-configuration\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_jwt\"\u003eJWT\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the \u003ca href=\"#_oauth2_introspection\"\u003eOAuth2 Introspection\u003c/a\u003e authenticator, this authenticator handles requests that have a Bearer token in the \u003ccode\u003eAuthorization\u003c/code\u003e header, in a different header, a query parameter or a body parameter as well. Unlike the OAuth2 Introspection authenticator it expects the token to be a JSON Web Token (JWT) and verifies it according \u003ca href=\"https://www.rfc-editor.org/rfc/rfc7519#section-7.2\"\u003eRFC 7519, Section 7.2\u003c/a\u003e. It does however not support encrypted payloads and nested JWTs. In addition to this, validation includes the verification of the time validity. Latter can be adjusted by specifying a leeway. All other validation options can and should be configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ejwt\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ejwks_endpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (dependant, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe JWKS endpoint, this authenticator retrieves the key material in a format specified in \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7519\"\u003eRFC 7519\u003c/a\u003e from for JWT signature verification purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this property is mutually exclusive with \u003ccode\u003emetadata_endpoint\u003c/code\u003e. If used, at least the \u003ccode\u003eurl\u003c/code\u003e must be configured. By default \u003ccode\u003emethod\u003c/code\u003e is set to \u003ccode\u003eGET\u003c/code\u003e and the HTTP \u003ccode\u003eAccept\u003c/code\u003e header to \u003ccode\u003eapplication/json\u003c/code\u003e. The path part of the \u003ccode\u003eurl\u003c/code\u003e can be \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003etemplated\u003c/a\u003e and has access to the \u003ccode\u003eTokenIssuer\u003c/code\u003e object, which is a string and basically holds the value of the \u003ccode\u003eiss\u003c/code\u003e claim from the token.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emetadata_endpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (dependant, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414\"\u003eOAuth 2.0 Authorization Server Metadata\u003c/a\u003e endpoint of the OAuth2, respectively OIDC authorization provider (the \u003ca href=\"https://openid.net/specs/openid-connect-discovery-1_0.html\"\u003eOpenID Connect Discovery\u003c/a\u003e specification is an OIDC specific profile of that specification). If the JWKS URL is not known upfront, it can be resolved by making use of that endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this property is mutually exclusive with \u003ccode\u003ejwks_endpoint\u003c/code\u003e. If used, at least the \u003ccode\u003eurl\u003c/code\u003e must be configured. As with the \u003ccode\u003ejwks_endpoint\u003c/code\u003e, the path part of the \u003ccode\u003eurl\u003c/code\u003e can be templated and has access to the \u003ccode\u003eTokenIssuer\u003c/code\u003e object already introduced above.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with the \u003ccode\u003ejwks_endpoint\u003c/code\u003e as well, the \u003ccode\u003emetadata_endpoint\u003c/code\u003e is by default configured to use \u003ccode\u003eGET\u003c/code\u003e as HTTP method and sets the \u003ccode\u003eAccept\u003c/code\u003e header to \u003ccode\u003eapplication/json\u003c/code\u003e, as also required by both specifications referenced above. In addition, to avoid useless communication, it is also configured to make use of HTTP cache according to \u003ca href=\"https://tools.ietf.org/html/rfc7234\"\u003eRFC 7234\u003c/a\u003e with default HTTP cache ttl set to \u003ccode\u003e30m\u003c/code\u003e. All these settings can however be overridden if required.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition to the properties specified by the \u003ca href=\"/docs/configuration/types/#_endpoint\"\u003e\u003ccode\u003eendpoint\u003c/code\u003e\u003c/a\u003e type, following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edisable_issuer_identifier_verification\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUpon retrieval of the server metadata, both, the \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414\"\u003eOAuth 2.0 Authorization Server Metadata\u003c/a\u003e RFC, and the \u003ca href=\"https://openid.net/specs/openid-connect-discovery-1_0.html\"\u003eOpenID Connect Discovery\u003c/a\u003e specification, require the verification of the issuer identifier for security reasons, e.g. to prevent \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414#section-6.2\"\u003eSpoofing Attacks\u003c/a\u003e. There are however setups, where strictly following that recommendation would result in extended bandwidth usage (instead of communicating directly with the auth server within the cluster one would need to use the same domain, the client application uses, which introduces additional network hops). It might also not work at all as the actual identifier of the issuer would change depending on where the request come from. By making use of this property and setting it to \u003ccode\u003etrue\u003c/code\u003e, one can disable the corresponding verification. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ejwt_source\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_authentication_data_source\"\u003eAuthentication Data Source\u003c/a\u003e\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to get the access token from. Defaults to retrieve it from the \u003ccode\u003eAuthorization\u003c/code\u003e header, the \u003ccode\u003eaccess_token\u003c/code\u003e query parameter or the \u003ccode\u003eaccess_token\u003c/code\u003e body parameter (latter, if the body is of \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e MIME type).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eassertions\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_assertions\"\u003eAssertions\u003c/a\u003e\u003c/em\u003e (dependant, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfigures the required claim assertions. Overriding on rule level is possible even partially. Those parts of the assertion, which have not been overridden are taken from the prototype configuration. If \u003ccode\u003emetadata_endpoint\u003c/code\u003e is used, the list of issuers is optional, as the issuer will be resolved via the auth server metadata document. Otherwise, the list of issuers is mandatory.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esubject\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_subject\"\u003eSubject\u003c/a\u003e\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to extract the subject id from the JWT, as well as which attributes to use. If not configured \u003ccode\u003esub\u003c/code\u003e is used to extract the subject id and all attributes from the JWT payload are made available as attributes of the subject.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow long to cache the key from the JWKS response, which was used for signature verification purposes. If not set, heimdall will cache this key for 10 minutes and not call JWKS endpoint again if the same \u003ccode\u003ekid\u003c/code\u003e is referenced in an JWT and same JWKS endpoint is used. The cache key is calculated from the \u003ccode\u003ejwks_endpoint\u003c/code\u003e configuration and the \u003ccode\u003ekid\u003c/code\u003e referenced in the JWT.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_fallback_on_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf set to \u003ccode\u003etrue\u003c/code\u003e, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalidate_jwk\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables or disables the verification of the JWK certificate used for JWT signature verification purposes. Effective only if the JWK contains a certificate. The verification happens according to \u003ca href=\"https://www.rfc-editor.org/rfc/rfc5280#section-6.1\"\u003eRFC 5280, section 6.1\u003c/a\u003e and also includes the check, that the certificate is allowed to be used for signature verification purposes. Revocation check is not supported. Defaults to \u003ccode\u003etrue\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etrust_store\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe path to a PEM file containing the trust anchors, to be used for the JWK certificate validation. Defaults to system trust store.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf a JWT does not reference a \u003ccode\u003ekid\u003c/code\u003e, heimdall always fetches a JWKS from the configured endpoint (so no caching is done) and iterates over the received keys until one matches. If none matches, the authenticator fails.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 9. Minimal possible configuration based on the JWKS endpoint\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eat_jwt\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ejwks_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://hydra:4444/.well-known/jwks.json\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4444/\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 10. Configuration for Keycloak utilizing metadata discovery\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emetadata_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://keycloak:8080/realms/my-app/.well-known/openid-configuration\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# Note that no assertions are configured here, since it\u0026#39;ll be resolved via the metadata endpoint\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Authenticators","url":"/docs/mechanisms/authenticators/"},{"categories":null,"content":" Some of the authorizers may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overriddable and partially overridable to indicate whether the property can be overridden in a rule pipeline.\nAllow As the name implies, this authorizer allows any request passing through. This authorizer type also doesn’t have any configuration options.\nTo enable the usage of this authorizer, you have to set the type property to allow.\nExample 1. Configuration of Allow authorizer id: allow_any_request type: allow Deny As the name implies, this authorizer denies any request (on HTTP response code level this is then mapped to 403 Forbidden). It basically stops the successful execution of the pipeline resulting in the execution of the error handler mechanisms. This authorizer type doesn’t have any configuration options.\nTo enable the usage of this authorizer, you have to set the type property to deny.\nExample 2. Configuration of Deny authorizer id: deny_any_request type: deny Local (CEL) This authorizer allows definition of authorization requirements based on information available about the authenticated subject, the existing pipeline results, as well as the actual request by using CEL based authorization expressions. Each expression is expected to return true to signal success. Otherwise, the authorization fails, resulting in the execution of the error handler mechanisms.\nTo enable the usage of this authorizer, you have to set the type property to cel.\nConfiguration using the config property is mandatory. Following properties are available:\nexpressions: Authorization Expression array (mandatory, overridable)\nList of authorization expressions, which define the actual authorization logic. Each expression has access to the Subject, Outputs, and the Request objects.\nExample 3. Authorization based on subject properties In this example the subject is checked to be member of the \u0026#34;admin\u0026#34; group.\nid: user_is_admin type: cel config: expressions: - expression: | has(Subject.Attributes.groups) \u0026amp;\u0026amp; Subject.Attributes.groups.exists(g, g == \u0026#34;admin\u0026#34;) message: User is not admin The first line of the expressions verifies that the property group exists. The second line checks, whether groups contains an entry named admin.\nThis example specifies also a message, which is logged, if the expression fails.\nExample 4. Authorization based on subject and request properties In this example the authorizer is configured to ensure anonymous access to a resource is possible for read requests only.\nid: no_modification_allowed_by_anonymous type: cel config: expressions: - expression: | Request.Method in [\u0026#34;GET\u0026#34;, \u0026#34;HEAD\u0026#34;, \u0026#34;OPTIONS\u0026#34;] || Subject.ID != \u0026#34;anonymous\u0026#34; message: Anonymous non-read access is forbidden The usage of this type of configuration makes sense in a pipeline, which combines multiple Authenticators, allowing anonymous and authenticated access.\nRemote This authorizer allows communication with other systems, like Open Policy Agent, Ory Keto, etc. for the actual authorization purpose. If the used endpoint answers with a not 2xx HTTP response code, this authorizer assumes, the authorization has failed, resulting in the execution of the error handler mechanisms. Otherwise, if no expressions for the verification of the response are defined, the authorizer assumes, the request has been authorized. If expressions are defined and do not fail, the authorization succeeds.\nIf your authorization system provides a payload in the response, heimdall inspects the Content-Type header to prepare the payload for further usage, e.g. for payload verification expressions, or for a Local (CEL) authorizer. If the content type does either end with json or is application/x-www-form-urlencoded, the payload is decoded, so key based access to the corresponding attributes is possible, otherwise it is made available as well, but as a simple string. In all cases this value is available for the authorization expressions, as well as in the Outputs property under a key named by the id of the authorizer (See also the example below).\nTo enable the usage of this authorizer, you have to set the type property to remote.\nConfiguration using the config property is mandatory. Following properties are available:\nendpoint: Endpoint (mandatory, not overridable)\nThe API endpoint of your authorization system. At least the url must be configured. This mechanism allows templating of the url and makes the Subject object, the Outputs object, as well as the Values (see also below) objects available to it. By default, this authorizer will use HTTP POST to send the rendered payload to this endpoint. You can override this behavior by configuring method as well. Depending on the API requirements of your authorization system, you might need to configure further properties, like headers, etc.\npayload: string (optional, overridable)\nYour template with definitions required to communicate to the authorization endpoint. The template can make use of Values, Outputs, Subject and Request objects.\nexpressions: Authorization Expression array (optional, overridable)\nList of CEL expressions which define the logic to be applied to the response returned by the endpoint. All expressions are expected to evaluate to true if the authorization was successful. If any of the expressions evaluates to false, the authorization fails and the message defined by the failed expression will be logged.\nEach expression has access to the Payload object.\nforward_response_headers_to_upstream: string array (optional, overridable)\nEnables forwarding of any headers from the authorization endpoint response to the upstream service.\ncache_ttl: Duration (optional, overridable)\nAllows caching of the authorization endpoint responses. Defaults to 0s, which means no caching. The cache key is calculated from the entire configuration of the authorizer instance and the available information about the current subject.\nvalues map of strings (optional, overridable)\nA key value map, which is made accessible to the template rendering engine as Values object, to render parts of the URL and/or the payload. The actual values in that map can be templated as well with access to the Subject, the Outputs, and Request objects.\nExample 5. Configuration of Remote authorizer to communicate with Open Policy Agent (OPA) Here the remote authorizer is configured to communicate with OPA. Since OPA expects the query to be formatted as JSON, the corresponding Content-Type header is set. Since the responses are JSON objects as well, the Accept header is also provided. In addition, this examples uses the basic_auth auth type to authenticate against the endpoint.\nid: opa type: remote config: endpoint: url: https://opa.local/v1/data/{{ .Values.namespace }}/{{ .Values.policy }} headers: Content-Type: json Accept: json auth: type: basic_auth config: user: ${OPA_USER} password: ${OPA_PASSWORD} payload: | { \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }} }, \u0026#34;some_data\u0026#34;: {{ quote .Values.whatever }}, \u0026#34;more_data\u0026#34;: {{ quote .Outputs.whatever }} } values: namespace: myapi/policy policy: allow_write whatever: | {{ .Request.Header(\u0026#34;X-Whatever\u0026#34;) }} expressions: - expression: | Payload.result == true message: User does not have required permissions In this case, since an OPA response could look like { \u0026#34;result\u0026#34;: true } or { \u0026#34;result\u0026#34;: false }, heimdall makes the response also available under Outputs[\u0026#34;opa\u0026#34;], with \u0026#34;opa\u0026#34; being the id of the authorizer in this example.\nA specific rule could then use this authorizer in the following ways:\n- id: rule1 # other rule properties execute: - # other mechanisms - authorizer: opa # using defaults - # other mechanisms - id: rule2 # other rule properties execute: - # other mechanisms - authorizer: opa config: # overriding with rule specifics values: policy: allow_read whatever: | {{ .Request.Header(\u0026#34;X-SomethingElse\u0026#34;) }} - # other mechanisms ","description":"Authorizers ensure that only those subjects, which are eligible can access the desired resource. This page describes the available authorizer types in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome of the authorizers may support or require additional configuration. The corresponding properties are annotated with \u003ccode\u003emandatory\u003c/code\u003e, respectively \u003ccode\u003eoptional\u003c/code\u003e to denote configuration requirement, as well as with \u003ccode\u003eoverridable\u003c/code\u003e, \u003ccode\u003enot overriddable\u003c/code\u003e and \u003ccode\u003epartially overridable\u003c/code\u003e to indicate whether the property can be overridden in a rule pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_allow\"\u003eAllow\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this authorizer allows any request passing through. This authorizer type also doesn’t have any configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authorizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eallow\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Configuration of Allow authorizer\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow_any_request\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_deny\"\u003eDeny\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this authorizer denies any request (on HTTP response code level this is then mapped to \u003ccode\u003e403 Forbidden\u003c/code\u003e). It basically stops the successful execution of the pipeline resulting in the execution of the error handler mechanisms. This authorizer type doesn’t have any configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authorizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003edeny\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Configuration of Deny authorizer\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_any_request\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_local_cel\"\u003eLocal (CEL)\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authorizer allows definition of authorization requirements based on information available about the authenticated subject, the existing pipeline results, as well as the actual request by using \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e based authorization expressions. Each expression is expected to return \u003ccode\u003etrue\u003c/code\u003e to signal success. Otherwise, the authorization fails, resulting in the execution of the error handler mechanisms.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authorizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ecel\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexpressions\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_authorization_expression\"\u003eAuthorization Expression\u003c/a\u003e array\u003c/em\u003e (mandatory, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eList of authorization expressions, which define the actual authorization logic. Each expression has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e, and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Authorization based on subject properties\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example the subject is checked to be member of the \u0026#34;admin\u0026#34; group.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003euser_is_admin\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ehas(Subject.Attributes.groups) \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eSubject.Attributes.groups.exists(g, g == \u0026#34;admin\u0026#34;)\u003c/span\u003e\n \u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eUser is not admin\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe first line of the expressions verifies that the property group exists. The second line checks, whether \u003ccode\u003egroups\u003c/code\u003e contains an entry named \u003ccode\u003eadmin\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example specifies also a message, which is logged, if the expression fails.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Authorization based on subject and request properties\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example the authorizer is configured to ensure anonymous access to a resource is possible for read requests only.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eno_modification_allowed_by_anonymous\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eRequest.Method in [\u0026#34;GET\u0026#34;, \u0026#34;HEAD\u0026#34;, \u0026#34;OPTIONS\u0026#34;] || Subject.ID != \u0026#34;anonymous\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAnonymous non-read access is forbidden\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe usage of this type of configuration makes sense in a pipeline, which combines multiple \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eAuthenticators\u003c/a\u003e, allowing anonymous and authenticated access.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_remote\"\u003eRemote\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authorizer allows communication with other systems, like \u003ca href=\"https://www.openpolicyagent.org/\"\u003eOpen Policy Agent\u003c/a\u003e, \u003ca href=\"https://www.ory.sh/docs/keto/\"\u003eOry Keto\u003c/a\u003e, etc. for the actual authorization purpose. If the used endpoint answers with a not 2xx HTTP response code, this authorizer assumes, the authorization has failed, resulting in the execution of the error handler mechanisms. Otherwise, if no expressions for the verification of the response are defined, the authorizer assumes, the request has been authorized. If expressions are defined and do not fail, the authorization succeeds.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf your authorization system provides a payload in the response, heimdall inspects the \u003ccode\u003eContent-Type\u003c/code\u003e header to prepare the payload for further usage, e.g. for payload verification expressions, or for a \u003ca href=\"#_local_cel\"\u003eLocal (CEL)\u003c/a\u003e authorizer. If the content type does either end with \u003ccode\u003ejson\u003c/code\u003e or is \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e, the payload is decoded, so key based access to the corresponding attributes is possible, otherwise it is made available as well, but as a simple string. In all cases this value is available for the authorization expressions, as well as in the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e property under a key named by the \u003ccode\u003eid\u003c/code\u003e of the authorizer (See also the example below).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authorizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eremote\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eendpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe API endpoint of your authorization system. At least the \u003ccode\u003eurl\u003c/code\u003e must be configured. This mechanism allows templating of the url and makes the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e object, the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e object, as well as the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e (see also below) objects available to it. By default, this authorizer will use HTTP \u003ccode\u003ePOST\u003c/code\u003e to send the rendered payload to this endpoint. You can override this behavior by configuring \u003ccode\u003emethod\u003c/code\u003e as well. Depending on the API requirements of your authorization system, you might need to configure further properties, like headers, etc.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epayload\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYour \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003etemplate\u003c/a\u003e with definitions required to communicate to the authorization endpoint. The template can make use of \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexpressions\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_authorization_expression\"\u003eAuthorization Expression\u003c/a\u003e array\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eList of \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e expressions which define the logic to be applied to the response returned by the endpoint. All expressions are expected to evaluate to \u003ccode\u003etrue\u003c/code\u003e if the authorization was successful. If any of the expressions evaluates to \u003ccode\u003efalse\u003c/code\u003e, the authorization fails and the message defined by the failed expression will be logged.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach expression has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_payload\"\u003e\u003ccode\u003ePayload\u003c/code\u003e\u003c/a\u003e object.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_response_headers_to_upstream\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables forwarding of any headers from the authorization endpoint response to the upstream service.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAllows caching of the authorization endpoint responses. Defaults to 0s, which means no caching. The cache key is calculated from the entire configuration of the authorizer instance and the available information about the current subject.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalues\u003c/code\u003e\u003c/strong\u003e \u003cem\u003emap of strings\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA key value map, which is made accessible to the template rendering engine as \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e object, to render parts of the URL and/or the payload. The actual values in that map can be templated as well with access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e, the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e, and \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Configuration of Remote authorizer to communicate with \u003ca href=\"https://www.openpolicyagent.org/\"\u003eOpen Policy Agent\u003c/a\u003e (OPA)\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere the remote authorizer is configured to communicate with OPA. Since OPA expects the query to be formatted as JSON, the corresponding \u003ccode\u003eContent-Type\u003c/code\u003e header is set. Since the responses are JSON objects as well, the \u003ccode\u003eAccept\u003c/code\u003e header is also provided. In addition, this examples uses the \u003ccode\u003ebasic_auth\u003c/code\u003e auth type to authenticate against the endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopa\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://opa.local/v1/data/{{ .Values.namespace }}/{{ .Values.policy }}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eContent-Type\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejson\u003c/span\u003e\n \u003cspan class=\"na\"\u003eAccept\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejson\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${OPA_USER}\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${OPA_PASSWORD}\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{ \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }} }, \u0026#34;some_data\u0026#34;: {{ quote .Values.whatever }}, \u0026#34;more_data\u0026#34;: {{ quote .Outputs.whatever }} }\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emyapi/policy\u003c/span\u003e\n \u003cspan class=\"na\"\u003epolicy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow_write\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewhatever\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ .Request.Header(\u0026#34;X-Whatever\u0026#34;) }}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.result == true\u003c/span\u003e\n \u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eUser does not have required permissions\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this case, since an OPA response could look like \u003ccode\u003e{ \u0026#34;result\u0026#34;: true }\u003c/code\u003e or \u003ccode\u003e{ \u0026#34;result\u0026#34;: false }\u003c/code\u003e, heimdall makes the response also available under \u003ccode\u003eOutputs[\u0026#34;opa\u0026#34;]\u003c/code\u003e, with \u003ccode\u003e\u0026#34;opa\u0026#34;\u003c/code\u003e being the id of the authorizer in this example.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA specific rule could then use this authorizer in the following ways:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule1\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other rule properties\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopa\u003c/span\u003e \u003cspan class=\"c1\"\u003e# using defaults\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\n\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule2\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other rule properties\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopa\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"c1\"\u003e# overriding with rule specifics\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epolicy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow_read\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewhatever\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ .Request.Header(\u0026#34;X-SomethingElse\u0026#34;) }}\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Authorizers","url":"/docs/mechanisms/authorizers/"},{"categories":null,"content":" Some of the contextualizers may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overriddable and partially overridable to indicate whether the property can be overridden in a rule pipeline.\nGeneric This mechanism allows you to communicate to any API you want to fetch further information about the subject. Typical scenario is getting specific attributes for later authorization purposes which are not known to the authentication system and thus were not made available in Subject’s Attributes property. If the API responses with a 2xx HTTP response code, the payload is made available in the Outputs object, otherwise, if not overridden, an error is thrown and the execution of the authentication \u0026amp; authorization pipeline stops. To avoid overwriting of existing key value pairs, this object is however not available on the top level, but under a key named by the id of the contextualizer (See also the example below). If the Content-Type of the response is either ending with json or is application/x-www-form-urlencoded, the payload is decoded and made available as map, otherwise it is treated as string, but, as written above, is made available as well.\nTo enable the usage of this contextualizer, you have to set the type property to generic.\nConfiguration using the config property is mandatory. Following properties are available:\nendpoint: Endpoint (mandatory, not overridable)\nThe API of the service providing additional attributes about the authenticated user. At least the url must be configured. This mechanism allows templating of the url and makes the Subject, the Outputs object, as well as the Values (see also below) objects available to it. By default, this contextualizer will use HTTP POST to send the rendered payload to this endpoint. You can override this behavior by configuring method as well. Depending on the API requirements of the system, this contextualizer should communicate to, you might need to configure further properties, like headers, etc.\nforward_headers: string array (optional, overridable)\nIf the API requires any headers from the request to heimdall, you can forward these unchanged by making use of this property\nforward_cookies: string array (optional, overridable)\nIf the API requires any cookies from the request to heimdall, you can forward these unchanged by making use of this property.\npayload: string (optional, overridable)\nYour template with definitions required to communicate to the endpoint. The template can make use of Values, Subject, the Outputs, and Request objects.\ncache_ttl: Duration (optional, overridable)\nAllows caching of the API responses. Defaults to 10 seconds. The cache key is calculated from the entire configuration of the contextualizer instance and the available information about the current subject.\ncontinue_pipeline_on_error: boolean (optional, overridable)\nIf set to true, allows the pipeline to continue with the execution of the next mechanisms. So the error, if thrown, is ignored. Defaults to false, which means the execution of the authentication \u0026amp; authorization pipeline is stopped and the execution of the error pipeline is started.\nvalues map of strings (optional, overridable)\nA key value map, which is made accessible to the template rendering engine as Values object to render parts of the URL and/or the payload. The actual values in that map can be templated as well with access to the Subject, the Outputs and Request objects.\nExample 1. Contextualizer configuration without payload In this example the contextualizer is configured to call an endpoint using the HTTP GET method with the subject id being part of the url path. As the endpoint requires the X-My-Session-Cookie cookie for subject authentication purposes, forward_cookies is used to achieve this.\nid: foo type: generic config: endpoint: url: https://some-other.service/users/{{.Subject.ID}} method: GET forward_cookies: - X-My-Session-Cookie Example 2. Contextualizer configuration with payload In this example the contextualizer is configured to call an endpoint using the HTTP POST and send some data.\nid: foo type: generic config: endpoint: url: https://some-other.service/users method: POST payload: | { \u0026#34;user_id\u0026#34;: {{ quote .Values.user_id }} \u0026#34;whatever\u0026#34;: {{ quote .Outputs.whatever }} } Since the values property is not defined but used in the payload, it must be specified in a rule making use of this contextualzer, e.g. in the following way:\n- id: rule1 # other rule properties execute: - # other mechanisms - contextualizer: foo config: # overriding with rule specifics values: user_id: \u0026#34;{{ .Subject.ID }}\u0026#34; - # other mechanisms ","description":"Contextualizers allow you enriching the information about the request and the authenticated subject. This page describes the available contextualizer types in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome of the contextualizers may support or require additional configuration. The corresponding properties are annotated with \u003ccode\u003emandatory\u003c/code\u003e, respectively \u003ccode\u003eoptional\u003c/code\u003e to denote configuration requirement, as well as with \u003ccode\u003eoverridable\u003c/code\u003e, \u003ccode\u003enot overriddable\u003c/code\u003e and \u003ccode\u003epartially overridable\u003c/code\u003e to indicate whether the property can be overridden in a rule pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_generic\"\u003eGeneric\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis mechanism allows you to communicate to any API you want to fetch further information about the subject. Typical scenario is getting specific attributes for later authorization purposes which are not known to the authentication system and thus were not made available in \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject’s\u003c/code\u003e\u003c/a\u003e \u003ccode\u003eAttributes\u003c/code\u003e property. If the API responses with a 2xx HTTP response code, the payload is made available in the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e object, otherwise, if not overridden, an error is thrown and the execution of the authentication \u0026amp; authorization pipeline stops. To avoid overwriting of existing key value pairs, this object is however not available on the top level, but under a key named by the \u003ccode\u003eid\u003c/code\u003e of the contextualizer (See also the example below). If the \u003ccode\u003eContent-Type\u003c/code\u003e of the response is either ending with \u003ccode\u003ejson\u003c/code\u003e or is \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e, the payload is decoded and made available as map, otherwise it is treated as string, but, as written above, is made available as well.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this contextualizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003egeneric\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eendpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe API of the service providing additional attributes about the authenticated user. At least the \u003ccode\u003eurl\u003c/code\u003e must be configured. This mechanism allows templating of the url and makes the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e, the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e object, as well as the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e (see also below) objects available to it. By default, this contextualizer will use HTTP \u003ccode\u003ePOST\u003c/code\u003e to send the rendered payload to this endpoint. You can override this behavior by configuring \u003ccode\u003emethod\u003c/code\u003e as well. Depending on the API requirements of the system, this contextualizer should communicate to, you might need to configure further properties, like headers, etc.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_headers\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the API requires any headers from the request to heimdall, you can forward these unchanged by making use of this property\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_cookies\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the API requires any cookies from the request to heimdall, you can forward these unchanged by making use of this property.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epayload\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYour \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003etemplate\u003c/a\u003e with definitions required to communicate to the endpoint. The template can make use of \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e, the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e, and \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAllows caching of the API responses. Defaults to 10 seconds. The cache key is calculated from the entire configuration of the contextualizer instance and the available information about the current subject.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003econtinue_pipeline_on_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf set to \u003ccode\u003etrue\u003c/code\u003e, allows the pipeline to continue with the execution of the next mechanisms. So the error, if thrown, is ignored. Defaults to \u003ccode\u003efalse\u003c/code\u003e, which means the execution of the authentication \u0026amp; authorization pipeline is stopped and the execution of the error pipeline is started.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalues\u003c/code\u003e\u003c/strong\u003e \u003cem\u003emap of strings\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA key value map, which is made accessible to the template rendering engine as \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e object to render parts of the URL and/or the payload. The actual values in that map can be templated as well with access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e, the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Contextualizer configuration without payload\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example the contextualizer is configured to call an endpoint using the HTTP \u003ccode\u003eGET\u003c/code\u003e method with the subject id being part of the url path. As the endpoint requires the \u003ccode\u003eX-My-Session-Cookie\u003c/code\u003e cookie for subject authentication purposes, \u003ccode\u003eforward_cookies\u003c/code\u003e is used to achieve this.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://some-other.service/users/{{.Subject.ID}}\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_cookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eX-My-Session-Cookie\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Contextualizer configuration with payload\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example the contextualizer is configured to call an endpoint using the HTTP \u003ccode\u003ePOST\u003c/code\u003e and send some data.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://some-other.service/users\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ePOST\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;user_id\u0026#34;: {{ quote .Values.user_id }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;whatever\u0026#34;: {{ quote .Outputs.whatever }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince the \u003ccode\u003evalues\u003c/code\u003e property is not defined but used in the payload, it must be specified in a rule making use of this contextualzer, e.g. in the following way:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule1\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other rule properties\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"c1\"\u003e# overriding with rule specifics\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Contextualizers","url":"/docs/mechanisms/contextualizers/"},{"categories":null,"content":" Some finalizers may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overriddable and partially overridable to indicate whether the property can be overridden in a rule pipeline.\nNoop As the name implies, this finalizer does nothing. This finalizer type also doesn’t have any configuration options.\nTo enable the usage of this finalizer, you have to set the type property to noop.\nExample 1. Noop finalizer configuration id: foo type: noop Header This finalizer enables transformation of a Subject and the Outputs objects into HTTP headers. It can also be used to map information from the original Request into headers expected by the upstream service.\nTo enable the usage of this finalizer, you have to set the type property to header.\nConfiguration using the config property is mandatory. Following properties are available:\nheaders: string map (mandatory, overridable)\nEnables configuration of arbitrary headers with any values build from available information (See also Templating).\nExample 2. Header finalizer configuration id: foo type: header config: headers: X-User-ID: \u0026#39;{{ quote .Subject.ID }}\u0026#39; X-User-Email: \u0026#39;{{ index .Subject.Attributes \u0026#34;email\u0026#34; | quote }}\u0026#39; Host: \u0026#39;{{ .Request.Header \u0026#34;Host\u0026#34; | quote }}\u0026#39; Cookie This finalizer enables transformation of a Subject and the Outputs objects into cookies. It can also be used to map information from the original Request into cookies expected by the upstream service.\nTo enable the usage of this finalizer, you have to set the type property to cookie.\nConfiguration using the config property is mandatory. Following properties are available:\ncookies: string map (mandatory, overridable)\nEnables configuration of arbitrary cookies with any values build from available information (See also Templating).\nExample 3. Cookie finalizer configuration id: foo type: cookies config: cookies: user_id_cookie: \u0026#39;{{ quote .Subject.ID }}\u0026#39; user_email_cookie: \u0026#39;{{ index .Subject.Attributes \u0026#34;email\u0026#34; | quote }}\u0026#39; JWT This finalizer enables transformation of the Subject and the Outputs objects as custom claims into a token in a JWT format, which is then made available to your upstream service in either the HTTP Authorization header with Bearer scheme set, or in a custom header. Your upstream service can then verify the signature of the JWT by making use of heimdall’s JWKS endpoint to retrieve the required public keys/certificates from.\nTo enable the usage of this finalizer, you have to set the type property to jwt.\nConfiguration using the config property is optional. Following properties are available:\nsigner: Signer (mandatory, not overridable)\nThe configuration of the key material used for signature creation purposes, as well as the name used for the iss claim.\nclaims: string (optional, overridable)\nYour template with custom claims, you would like to add to the JWT (See also Templating).\nttl: Duration (optional, overridable)\nDefines how long the JWT should be valid. Defaults to 5 minutes. Heimdall sets the iat and the nbf claims to the current system time. The value of the exp claim is then influenced by the ttl property.\nheader: object (optional, not overridable)\nDefines the name and scheme to be used for the header. Defaults to Authorization with scheme Bearer. If defined, the name property must be set. If scheme is not defined, no scheme will be prepended to the resulting JWT.\nThe generated JWT is always cached until 5 seconds before its expiration. The cache key is calculated from the entire configuration of the finalizer instance and the available information about the current subject.\nExample 4. JWT finalizer configuration id: jwt_finalizer type: jwt config: ttl: 5m header: name: X-Token claims: | { {{ $user_name := .Subject.Attributes.identity.user_name -}} \u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.identity.email }}, \u0026#34;email_verified\u0026#34;: {{ .Subject.Attributes.identity.email_verified }}, \u0026#34;name\u0026#34;: {{ if $user_name }}{{ quote $user_name }}{{ else }}{{ quote $email }}{{ end }} } OAuth2 Client Credentials This finalizer drives the OAuth2 Client Credentials Grant flow to obtain a token, which should be used for communication with the upstream service. By default, as long as not otherwise configured (see the options below), the obtained token is made available to your upstream service in the HTTP Authorization header with Bearer scheme set. Unlike the other finalizers, it does not have access to any objects created by the rule execution pipeline.\nTo enable the usage of this finalizer, you have to set the type property to oauth2_client_credentials.\nConfiguration using the config property is mandatory. Following properties are available:\ntoken_url: string (mandatory, not overridable)\nThe token endpoint of the authorization server.\nclient_id: string (mandatory, not overridable)\nThe client identifier for heimdall.\nclient_secret: string (mandatory, not overridable)\nThe client secret for heimdall.\nauth_method: string (optional, not overridable)\nThe authentication method to be used according to RFC 6749, Client Password. Can be one of\nbasic_auth (default if auth_method is not set): With that authentication method, the \u0026#34;application/x-www-form-urlencoded\u0026#34; encoded values of client_id and client_secret are sent to the authorization server via the Authorization header using the Basic scheme.\nrequest_body: With that authentication method the client_id and client_secret are sent in the request body together with the other parameters (e.g. scopes) defined by the flow.\nUsage of request_body authentication method is not recommended and should be avoided. scopes: string array (optional, overridable)\nThe scopes required for the access token.\ncache_ttl: Duration (optional, overridable)\nHow long to cache the token received from the token endpoint. Defaults to the token expiration information from the token endpoint (the value of the expires_in field) if present. If the token expiration inforation is not present and cache_ttl is not configured, the received token is not cached. If the token expiration information is present in the response and cache_ttl is configured the shorter value is taken. If caching is enabled, the token is cached until 5 seconds before its expiration. To disable caching, set it to 0s. The cache key calculation is based on the entire oauth2_client_credentials configuration without considering the header property.\nheader: object (optional, overridable)\nDefines the name and scheme to be used for the header. Defaults to Authorization with scheme Bearer. If defined, the name property must be set. If scheme is not defined, no scheme will be prepended to the resulting JWT.\nExample 5. OAuth2 Client Credentials finalizer configuration id: get_token type: oauth2_client_credentials config: cache_ttl: 5m header: name: X-Token scheme: MyScheme token_url: https://my-oauth-provider.com/token client_id: my_client client_secret: VerySecret! auth_method: basic_auth scopes: - foo - bar ","description":"Finalizers are the last steps executed in a rule pipeline and can e.g. create a special representation of the subject to be made available to the upstream service. This page describes the available finalizer types in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome finalizers may support or require additional configuration. The corresponding properties are annotated with \u003ccode\u003emandatory\u003c/code\u003e, respectively \u003ccode\u003eoptional\u003c/code\u003e to denote configuration requirement, as well as with \u003ccode\u003eoverridable\u003c/code\u003e, \u003ccode\u003enot overriddable\u003c/code\u003e and \u003ccode\u003epartially overridable\u003c/code\u003e to indicate whether the property can be overridden in a rule pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_noop\"\u003eNoop\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this finalizer does nothing. This finalizer type also doesn’t have any configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this finalizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003enoop\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Noop finalizer configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_header\"\u003eHeader\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis finalizer enables transformation of a \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e objects into HTTP headers. It can also be used to map information from the original \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e into headers expected by the upstream service.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this finalizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eheader\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheaders\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring map\u003c/em\u003e (mandatory, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables configuration of arbitrary headers with any values build from available information (See also \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003eTemplating\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Header finalizer configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eX-User-ID\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eX-User-Email\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eindex\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.Attributes\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e|\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eHost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Request.Header\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;Host\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e|\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cookie\"\u003eCookie\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis finalizer enables transformation of a \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e objects into cookies. It can also be used to map information from the original \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e into cookies expected by the upstream service.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this finalizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ecookie\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecookies\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring map\u003c/em\u003e (mandatory, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables configuration of arbitrary cookies with any values build from available information (See also \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003eTemplating\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Cookie finalizer configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecookies\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser_id_cookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser_email_cookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eindex\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.Attributes\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e|\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_jwt\"\u003eJWT\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis finalizer enables transformation of the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e objects as custom claims into a token in a \u003ca href=\"https://www.rfc-editor.org/rfc/rfc7519\"\u003eJWT\u003c/a\u003e format, which is then made available to your upstream service in either the HTTP \u003ccode\u003eAuthorization\u003c/code\u003e header with \u003ccode\u003eBearer\u003c/code\u003e scheme set, or in a custom header. Your upstream service can then verify the signature of the JWT by making use of heimdall’s JWKS endpoint to retrieve the required public keys/certificates from.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this finalizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ejwt\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is optional. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esigner\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_signer\"\u003eSigner\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of the key material used for signature creation purposes, as well as the name used for the \u003ccode\u003eiss\u003c/code\u003e claim.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclaims\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYour template with custom claims, you would like to add to the JWT (See also \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003eTemplating\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ettl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines how long the JWT should be valid. Defaults to 5 minutes. Heimdall sets the \u003ccode\u003eiat\u003c/code\u003e and the \u003ccode\u003enbf\u003c/code\u003e claims to the current system time. The value of the \u003ccode\u003eexp\u003c/code\u003e claim is then influenced by the \u003ccode\u003ettl\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheader\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eobject\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines the \u003ccode\u003ename\u003c/code\u003e and \u003ccode\u003escheme\u003c/code\u003e to be used for the header. Defaults to \u003ccode\u003eAuthorization\u003c/code\u003e with scheme \u003ccode\u003eBearer\u003c/code\u003e. If defined, the \u003ccode\u003ename\u003c/code\u003e property must be set. If \u003ccode\u003escheme\u003c/code\u003e is not defined, no scheme will be prepended to the resulting JWT.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe generated JWT is always cached until 5 seconds before its expiration. The cache key is calculated from the entire configuration of the finalizer instance and the available information about the current subject.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. JWT finalizer configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_finalizer\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclaims\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ $user_name := .Subject.Attributes.identity.user_name -}}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.identity.email }},\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;email_verified\u0026#34;: {{ .Subject.Attributes.identity.email_verified }},\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;name\u0026#34;: {{ if $user_name }}{{ quote $user_name }}{{ else }}{{ quote $email }}{{ end }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_oauth2_client_credentials\"\u003eOAuth2 Client Credentials\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis finalizer drives the \u003ca href=\"https://www.rfc-editor.org/rfc/rfc6749#section-4.4\"\u003eOAuth2 Client Credentials Grant\u003c/a\u003e flow to obtain a token, which should be used for communication with the upstream service. By default, as long as not otherwise configured (see the options below), the obtained token is made available to your upstream service in the HTTP \u003ccode\u003eAuthorization\u003c/code\u003e header with \u003ccode\u003eBearer\u003c/code\u003e scheme set. Unlike the other finalizers, it does not have access to any objects created by the rule execution pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this finalizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eoauth2_client_credentials\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etoken_url\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe token endpoint of the authorization server.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclient_id\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe client identifier for heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclient_secret\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe client secret for heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauth_method\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe authentication method to be used according to \u003ca href=\"https://www.rfc-editor.org/rfc/rfc6749#section-2.3.1\"\u003eRFC 6749, Client Password\u003c/a\u003e. Can be one of\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ebasic_auth\u003c/code\u003e (default if \u003ccode\u003eauth_method\u003c/code\u003e is not set): With that authentication method, the \u003ccode\u003e\u0026#34;application/x-www-form-urlencoded\u0026#34;\u003c/code\u003e encoded values of \u003ccode\u003eclient_id\u003c/code\u003e and \u003ccode\u003eclient_secret\u003c/code\u003e are sent to the authorization server via the \u003ccode\u003eAuthorization\u003c/code\u003e header using the \u003ccode\u003eBasic\u003c/code\u003e scheme.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003erequest_body\u003c/code\u003e: With that authentication method the \u003ccode\u003eclient_id\u003c/code\u003e and \u003ccode\u003eclient_secret\u003c/code\u003e are sent in the request body together with the other parameters (e.g. \u003ccode\u003escopes\u003c/code\u003e) defined by the flow.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsage of \u003ccode\u003erequest_body\u003c/code\u003e authentication method is not recommended and should be avoided.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escopes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe scopes required for the access token.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow long to cache the token received from the token endpoint. Defaults to the token expiration information from the token endpoint (the value of the \u003ccode\u003eexpires_in\u003c/code\u003e field) if present. If the token expiration inforation is not present and \u003ccode\u003ecache_ttl\u003c/code\u003e is not configured, the received token is not cached. If the token expiration information is present in the response and \u003ccode\u003ecache_ttl\u003c/code\u003e is configured the shorter value is taken. If caching is enabled, the token is cached until 5 seconds before its expiration. To disable caching, set it to \u003ccode\u003e0s\u003c/code\u003e. The cache key calculation is based on the entire \u003ccode\u003eoauth2_client_credentials\u003c/code\u003e configuration without considering the \u003ccode\u003eheader\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheader\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eobject\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines the \u003ccode\u003ename\u003c/code\u003e and \u003ccode\u003escheme\u003c/code\u003e to be used for the header. Defaults to \u003ccode\u003eAuthorization\u003c/code\u003e with scheme \u003ccode\u003eBearer\u003c/code\u003e. If defined, the \u003ccode\u003ename\u003c/code\u003e property must be set. If \u003ccode\u003escheme\u003c/code\u003e is not defined, no scheme will be prepended to the resulting JWT.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. OAuth2 Client Credentials finalizer configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eget_token\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_client_credentials\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Token\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eMyScheme\u003c/span\u003e\n \u003cspan class=\"na\"\u003etoken_url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://my-oauth-provider.com/token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy_client\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_secret\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecret!\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_method\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Finalizers","url":"/docs/mechanisms/finalizers/"},{"categories":null,"content":" Some of the error handlers may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overriddable and partially overridable to indicate whether the property can be overridden in a rule pipeline.\nDefault This error handler is always there and is executed if no other error handler mechanism is responsible for the error. Actually, there is no need to explicitly configure it. The only exception is to allow overriding the default rule’s error handler chain in a specific rule for performance reasons (if configured error handlers in the default rule should not be considered). This mechanism type doesn’t have any configuration options.\nTo enable the usage of this mechanism, you have to set the type property to default.\nExample 1. Configuring Default error handler to enable referencing it from rules id: foo type: default Redirect This error handler mechanism allows redirecting the client to another endpoint, e.g. to let the user authenticate. Technically this error handler returns e.g. a HTTP 302 Found response code and sets the HTTP Location header.\nTo enable the usage of this mechanism, you have to set the type property to redirect.\nConfiguration is mandatory by making use of the config property supporting the following settings:\nto: URL (mandatory, not overridable)\nThe url to redirect the client to via the Location header. Can be templated and has access to the Request object.\nWhen creating query parameters by making use of templates, don’t forget to encode the values using the urlenc function. See also examples below. code: int (optional, not overridable)\nThe code to be used for the redirect. Defaults to 302 Found.\nHeimdall does not check the configured code for HTTP redirect validity! Example 2. Redirect error handler configuration The redirect error handler below is configured to kick in if the error is either authentication_error or authorization_error and the request come from a browser (HTTP Accept header contains text/html). If this condition holds true it will redirect the client to https://127.0.0.1:4433/self-service/login/browser and add the return_to query parameter set to the URL encoded value of the current url as well.\nSo, e.g. if heimdall was handling the request for https://my-service.local/foo and run into an error like described above, the HTTP response to the client will have the code 302 Found set and the Location header set to https://127.0.0.1:4433/self-service/login/browser?return_to=https%3A%2F%2Fmy-service.local%2Ffoo\nid: authenticate_with_kratos type: redirect config: to: https://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }} WWW-Authenticate This error handler mechanism responds with HTTP 401 Unauthorized and a WWW-Authenticate HTTP header set. As of now, this error handler is the only one error handler, which transforms heimdall into an authentication system, a very simple one though. By configuring this error handler you can implement the Basic HTTP Authentication Scheme by also making use of the Basic Auth authenticator. Without that authenticator, the usage of this error handler does actually not make any sense.\nTo enable the usage of this error handler, you have to set the type property to www_authenticate.\nConfiguration is mandatory by making use of the if and config properties. The first defines the condition, which must hold true for this error handler to execute and has access to the Request and the Error objects. Latter defines the data to drive the redirect and supports the following properties:\nrealm: string (optional, overridable)\nThe \u0026#34;realm\u0026#34; according to RFC 7235, section 2.2. Defaults to \u0026#34;Please authenticate\u0026#34;.\nExample 3. Configuration of WWW-Authenticate error handler The www authenticate error handler below is configured to kick in if an authentication_error error occurred (an error raised by authenticators) and has been raised by an authenticator with id equal to basic_auth_authenticator. In this case, it will respond with HTTP 401 Unauthorized and a WWW-Authenticate header set to Basic realm=\u0026#34;My fancy app\u0026#34;.\nid: basic_authenticate type: www_authenticate if: | Error.Source == \u0026#34;basic_auth_authenticator\u0026#34; \u0026amp;\u0026amp; type(Error) == authentication_error config: realm: \u0026#34;My fancy app\u0026#34; ","description":"Error handlers kick in when any of the stages of the regular rule pipeline fail and let you define logic to handle such situations. This page describes the available error handler types in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome of the error handlers may support or require additional configuration. The corresponding properties are annotated with \u003ccode\u003emandatory\u003c/code\u003e, respectively \u003ccode\u003eoptional\u003c/code\u003e to denote configuration requirement, as well as with \u003ccode\u003eoverridable\u003c/code\u003e, \u003ccode\u003enot overriddable\u003c/code\u003e and \u003ccode\u003epartially overridable\u003c/code\u003e to indicate whether the property can be overridden in a rule pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_default\"\u003eDefault\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis error handler is always there and is executed if no other error handler mechanism is responsible for the error. Actually, there is no need to explicitly configure it. The only exception is to allow overriding the \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule’s\u003c/a\u003e error handler chain in a specific rule for performance reasons (if configured error handlers in the default rule should not be considered). This mechanism type doesn’t have any configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this mechanism, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003edefault\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Configuring Default error handler to enable referencing it from rules\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_redirect\"\u003eRedirect\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis error handler mechanism allows redirecting the client to another endpoint, e.g. to let the user authenticate. Technically this error handler returns e.g. a HTTP \u003ccode\u003e302 Found\u003c/code\u003e response code and sets the HTTP \u003ccode\u003eLocation\u003c/code\u003e header.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this mechanism, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eredirect\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration is mandatory by making use of the \u003ccode\u003econfig\u003c/code\u003e property supporting the following settings:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eto\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eURL\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe url to redirect the client to via the \u003ccode\u003eLocation\u003c/code\u003e header. Can be templated and has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e object.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWhen creating query parameters by making use of templates, don’t forget to encode the values using the \u003ccode\u003eurlenc\u003c/code\u003e function. See also examples below.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecode\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eint\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe code to be used for the redirect. Defaults to \u003ccode\u003e302 Found\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nHeimdall does not check the configured code for HTTP redirect validity!\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Redirect error handler configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe redirect error handler below is configured to kick in if the error is either \u003ccode\u003eauthentication_error\u003c/code\u003e or \u003ccode\u003eauthorization_error\u003c/code\u003e and the request come from a browser (HTTP \u003ccode\u003eAccept\u003c/code\u003e header contains \u003ccode\u003etext/html\u003c/code\u003e). If this condition holds true it will redirect the client to \u003ccode\u003ehttps://127.0.0.1:4433/self-service/login/browser\u003c/code\u003e and add the \u003ccode\u003ereturn_to\u003c/code\u003e query parameter set to the URL encoded value of the current url as well.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSo, e.g. if heimdall was handling the request for \u003ccode\u003ehttps://my-service.local/foo\u003c/code\u003e and run into an error like described above, the HTTP response to the client will have the code \u003ccode\u003e302 Found\u003c/code\u003e set and the \u003ccode\u003eLocation\u003c/code\u003e header set to \u003ccode\u003ehttps://127.0.0.1:4433/self-service/login/browser?return_to=https%3A%2F%2Fmy-service.local%2Ffoo\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticate_with_kratos\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_www_authenticate\"\u003eWWW-Authenticate\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis error handler mechanism responds with HTTP \u003ccode\u003e401 Unauthorized\u003c/code\u003e and a \u003ccode\u003eWWW-Authenticate\u003c/code\u003e HTTP header set. As of now, this error handler is the only one error handler, which transforms heimdall into an authentication system, a very simple one though. By configuring this error handler you can implement the \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7617\"\u003eBasic HTTP Authentication Scheme\u003c/a\u003e by also making use of the \u003ca href=\"/docs/mechanisms/authenticators/#_basic_auth\"\u003eBasic Auth\u003c/a\u003e authenticator. Without that authenticator, the usage of this error handler does actually not make any sense.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this error handler, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ewww_authenticate\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration is mandatory by making use of the \u003ccode\u003eif\u003c/code\u003e and \u003ccode\u003econfig\u003c/code\u003e properties. The first defines the condition, which must hold true for this error handler to execute and has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_error\"\u003e\u003ccode\u003eError\u003c/code\u003e\u003c/a\u003e objects. Latter defines the data to drive the redirect and supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003erealm\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u0026#34;realm\u0026#34; according to \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7235#section-2.2\"\u003eRFC 7235, section 2.2\u003c/a\u003e. Defaults to \u0026#34;Please authenticate\u0026#34;.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Configuration of WWW-Authenticate error handler\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe www authenticate error handler below is configured to kick in if an \u003ccode\u003eauthentication_error\u003c/code\u003e error occurred (an error raised by authenticators) and has been raised by an authenticator with id equal to \u003ccode\u003ebasic_auth_authenticator\u003c/code\u003e. In this case, it will respond with HTTP \u003ccode\u003e401 Unauthorized\u003c/code\u003e and a \u003ccode\u003eWWW-Authenticate\u003c/code\u003e header set to \u003ccode\u003eBasic realm=\u0026#34;My fancy app\u0026#34;\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_authenticate\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ewww_authenticate\u003c/span\u003e\n\u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eError.Source == \u0026#34;basic_auth_authenticator\u0026#34; \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) == authentication_error\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003erealm\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eMy\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003efancy\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eapp\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Error Handlers","url":"/docs/mechanisms/error_handlers/"},{"categories":null,"content":" In the simplest case, a regular rule reuses mechanisms from the previously defined catalogue in its pipelines. In more complex scenarios, a rule can reconfigure parts of the mechanisms being used. The specific parts that can be reconfigured or overridden depend on the mechanism itself and are described in the mechanism-specific documentation. Reconfiguration is always limited to the particular rule’s pipeline and does not affect other rules.\nConfiguration A single regular rule consists of the following properties:\nid: string (mandatory)\nThe unique identifier of the rule. It must be unique across all rules loaded by the same Rule Provider. To ensure uniqueness, it’s recommended to include the upstream service’s name and the rule’s purpose in the id. For example, rule:my-service:public-api.\nmatch: RuleMatcher (mandatory)\nDefines the matching criteria for a rule, with the following properties:\nroutes: RouteMatcher array (mandatory)\nSpecifies route conditions for matching the rule to incoming HTTP requests with each entry having the following properties:\npath: string (mandatory)\nThe Path Expression describing the request path this rule should match. It supports both simple and free (named) wildcards.\npath_params: PathParameterConditions (optional)\nAdditional conditions for the values captured by named wildcards in the path expression. Each entry supports the following properties:\nname: string (mandatory)\nThe name of the wildcard.\ntype: string (mandatory)\nThe type of expression used to match the captured wildcard’s value. The supported types are:\nglob: to use a glob expression to match the captured value (/ is used as a delimiter, so * matches anything until the next /).\nregex to use a regular expression to match the captured value.\nvalue: string (mandatory)\nThe actual expression based on the given type.\nbacktracking_enabled: boolean (optional)\nEnables or disables backtracking when a request matches the path expressions but fails to meet additional matching criteria, like path_params, hosts, etc. This setting is inherited from the default rule and defaults to that rule’s setting. When enabled, the system will backtrack to attempt a match with a less specific rule (see Rule Matching Specificity \u0026amp; Backtracking for more details).\nhosts: HostMatcher array (optional)\nDefines a set of hosts to match against the HTTP Host header. Each entry has the following properties:\ntype: string (mandatory)\nSpecifies the type of expression for matching the host, which can be one of:\nexact to match the host exactly\nglob to use a glob expression which should be satisfied by the host of the incoming request (. is used as a delimiter, which means * will match anything until the next .).\nregex to use a regular expression which should be satisfied by the host of the incoming request.\nvalue: string (mandatory)\nThe actual host expression based on the type.\nscheme: string (optional)\nThe expected HTTP scheme. If not specified, both http and https are accepted.\nmethods: string array (optional)\nSpecifies the allowed HTTP methods (GET, POST, PATCH, etc). If not specified, all methods are allowed. To allow all methods except specific ones, use ALL and prefix the methods to exclude with !. For example:\n# Methods list which effectively expands to all HTTP methods methods: - ALL # Methods list consisting of all HTTP methods without `TRACE` and `OPTIONS` methods: - ALL - \u0026#34;!TRACE\u0026#34; - \u0026#34;!OPTIONS\u0026#34; allow_encoded_slashes: string (optional)\nControls how to handle URL-encoded slashes in request paths during matching and forwarding. Options include:\noff - Reject requests with encoded slashes (%2F). This is the default behavior.\non - Accept requests with encoded slashes decoding them to /.\nno_decode - Accept requests with encoded slashes without touching them.\nHandling URL-encoded slashes may differ across the proxies in front of heimdall, heimdall, and the upstream service. Accepting requests with encoded slashes could, depending on your rules, lead to Interpretation Conflict vulnerabilities resulting in privilege escalations. forward_to: RequestForwarder (mandatory in Proxy operation mode)\nSpecifies where to forward proxied requests when heimdall is operating in proxy mode. The following properties are supported:\nhost: string (mandatory)\nHost (and port) for forwarding the request. If no rewrite property (see below) is defined, the original URL’s scheme, path, and other components are preserved. E.g. if the original request is https://mydomain.com/api/v1/something?foo=bar\u0026amp;bar=baz and the value of this property is set to my-backend:8080, the url used to forward the request to the upstream will be https://my-backend:8080/api/v1/something?foo=bar\u0026amp;bar=baz\nThe Host header is not preserved when forwarding the request. To preserve it, use of the header finalizer in your execute pipeline and set it accordingly. The example below demonstrates that. rewrite: OriginalURLRewriter (optional)\nCan be used to rewrite further parts of the original URL before forwarding the request. If specified, at least one of the following supported (middleware) properties must be specified:\nscheme: string (optional)\nSpecifies the URL scheme to use when forwarding the request. Defaults to the scheme used in the original request.\nUnless heimdall is started with the --insecure-skip-upstream-tls-enforcement flag, only https is allowed as the scheme. strip_path_prefix: string (optional)\nThis middleware strips the specified prefix from the original URL path before forwarding. E.g. if the path of the original url is /api/v1/something and the value of this property is set to /api/v1, the request to the upstream will have the url path set to /something.\nadd_path_prefix: string (optional)\nThis middleware is applied after the execution of the strip_path_prefix middleware described above. If specified, heimdall will add the specified path prefix to the path used to forward the request to the upstream service. E.g. if the path of the original URL or the path resulting after the application of the strip_path_prefix middleware is /something and the value of this property is set to /my-backend, the request to the upstream will have the URL path set to /my-backend/something.\nstrip_query_parameters: string array (optional)\nRemoves specified query parameters from the original URL before forwarding. E.g. if the query parameters part of the original URL is foo=bar\u0026amp;bar=baz and the value of this property is set to [\u0026#34;foo\u0026#34;], the query part of the request to the upstream will be set to bar=baz\nexecute: Authentication \u0026amp; Authorization Pipeline (mandatory)\nSpecifies the mechanisms used for authentication, authorization, contextualization, and finalization.\non_error: Error Pipeline (optional)\nSpecifies error handling mechanisms if the pipeline defined by the execute property fails. Defaults to the error pipeline defined in the default rule if not specified.\nExample 1. An example rule id: rule:foo:bar match: routes: - path: /some/:identifier/followed/by/** path_params: - name: identifier type: glob value: \u0026#34;[a-z]\u0026#34; scheme: https hosts: - type: exact value: my-service.local methods: - GET - POST forward_to: host: backend-a:8080 rewrite: scheme: https strip_path_prefix: /api/v1 execute: # the following just demonstrates how to make use of specific # mechanisms in the simplest possible form - authenticator: foo - authorizer: bar - contextualizer: foo - finalizer: zab # the following one demonstrates how to preserve the # Host header from the original request, while forwarding # it to the upstream service - finalizer: preserve-host # the config property can be omitted, if already configured # in the header finalizer mechanism config: headers: Host: \u0026#39;{{ .Request.Header \u0026#34;Host\u0026#34; | quote }}\u0026#39; on_error: - error_handler: foobar Path Expression Path expressions are used to match the incoming requests. When specifying these, you can make use of two types of wildcards:\nfree wildcard, which can be defined using * and\nsingle wildcard, which can be defined using :\nBoth can be named and unnamed, with named wildcards allowing accessing of the matched segments in the pipeline of the rule using the defined name as a key on the Request.URL.Captures object. Unnamed free wildcard is defined as ** and unnamed single wildcard is defined as :*. A named wildcard uses some identifier instead of the *, so like *name for free wildcard and :name for single wildcard.\nThe value of the path segment, respectively path segments available via the wildcard name is decoded. E.g. if you define the to be matched path in a rule as /file/:name, and the actual path of the request is /file/%5Bid%5D, you’ll get [id] when accessing the captured path segment via the name key. Not every path encoded value is decoded though. Decoding of encoded slashes happens only if allow_encoded_slashes was set to on.\nThere are some simple rules, which must be followed while using wildcards:\nOne can use as many single wildcards, as needed in any segment\nA segment must start with : or * to define a wildcard\nNo segments are allowed after a free (named) wildcard\nIf a regular segment must start with : or *, but should not be considered as a wildcard, it must be escaped with \\.\nHere some path examples:\n/apples/and/bananas - Matches exactly the given path\n/apples/and/:something - Matches /apples/and/bananas, /apples/and/oranges and alike, but not /apples/and/bananas/andmore or /apples/or/bananas. Since a named single wildcard is used, the actual value of the path segment matched by :something can be accessed in the rule pipeline using something as a key.\n/apples/:junction/:something - Similar to above. But will also match /apples/or/bananas in addition to /apples/and/bananas and /apples/and/oranges.\n/apples/and/some:thing - Matches exactly /apples/and/some:thing\n/apples/and/some** - Matches exactly /apples/and/some**\n/apples/** - Matches any path starting with /apples/, like /apples/and/bananas but not /apples/.\n/apples/*remainingpath - Same as above, but uses a named free wildcard\n/apples/**/bananas - Is invalid, as there is a path segment after a free wildcard\n/apples/\\*remainingpath - Matches exactly /apples/*remainingpath\nHere is an example demonstrating the usage of a single named wildcard:\nid: rule:1 match: routes: - path: /files/:uuid/delete hosts: - type: exact value: hosty.mchostface execute: - authorizer: openfga_check config: payload: | { \u0026#34;user\u0026#34;: \u0026#34;{{ .Subject.ID }}\u0026#34;, \u0026#34;relation\u0026#34;: \u0026#34;can_delete\u0026#34;, \u0026#34;object\u0026#34;: \u0026#34;file:{{ .Request.URL.Captures.uuid }}\u0026#34; } Rule Matching Specificity \u0026amp; Backtracking The implementation ensures that rules with more specific path expressions are matched first, regardless of their placement within a rule set. In fact, more specific rules are prioritized even when they are defined across different rule sets.\nWhen a path expression matches a request, any additional conditions specified in the rule’s matching criteria are evaluated. Only if these conditions are met will the rule’s pipeline be executed.\nIf multiple rules share the same path expression and all their additional conditions match, the first matching rule will be applied. The matching order is determined by the sequence of rules in the rule set. If no rule is matched, and backtracking is enabled, the process will backtrack to attempt a match with the next less specific rule. Backtracking will stop when:\na less specific rule successfully matches (including evaluation of any additional conditions), or\na less specific rule fails to match and does not permit backtracking.\nThe following examples illustrate these principles:\nImagine the following set of rules\nid: rule1 match: routes: - path: /files/** execute: - \u0026lt;pipeline definition\u0026gt; id: rule2 match: routes: - path: /files/:team/:name path_params: - name: team type: regex value: \u0026#34;(team1|team2)\u0026#34; backtracking_enabled: true execute: - \u0026lt;pipeline definition\u0026gt; id: rule3 match: routes: - path: /files/team3/:name execute: - \u0026lt;pipeline definition\u0026gt; The request to /files/team1/document.pdf will be matched by rule2, as it is more specific than rule1. Consequently, the pipeline for rule2 will be executed.\nThe request to /files/team3/document.pdf will be matched by rule3, which is more specific than both rule1 and rule2. As a result, the corresponding pipeline will be executed.\nHowever, even though the request to /files/team4/document.pdf matches the path defined in rule2, the regular expression (team1|team2) used in the path_params for the team parameter will not match. Since backtracking_enabled is set to true, backtracking will occur, and the request will be matched by rule1, with its pipeline then being executed.\nAuthentication \u0026amp; Authorization Pipeline As described in the Concepts section, this pipeline consists of mechanisms, previously configured in the mechanisms catalogue, organized in stages as described below, with authentication stage (consisting of authenticators) being mandatory.\nAuthentication Stage: List of authenticator references using authenticator as key, followed by the required authenticator id. Authenticators following the first defined in the list are used by heimdall as fallback. That is, if first authenticator fails due to missing authentication data, second is executed, etc. By default, fallback is not used if an authenticator fails due to validation errors of the given authentication data. E.g. if an authenticator fails to validate the signature of a JWT token, the next authenticator in the list will not be executed. Instead, the entire pipeline will fail and lead to the execution of the error pipeline. This list is mandatory if no default rule is configured.\nSome authenticators use the same sources to get subject authentication object from. E.g. the jwt and the oauth2_introspection authenticators can retrieve tokens from the same places in the request. If such authenticators are used in the same pipeline, you should configure the more specific ones before the more general ones to have working default fallbacks. To stay with the above example, the jwt authenticator is more specific compared to oauth2_introspection, as it will be only executed, if the token is in a JWT format. In contrast to this, the oauth2_introspection authenticator is more general and does not care about the token format, thus will feel responsible for the request as soon as it finds a bearer token. You can however also make use of the allow_fallback_on_error configuration property and set it to true. This will allow a fallback even if the verification of the credentials fail. Authorization Stage: List of contextualizer and authorizer references in any order (optional). Can also be mixed. As with authenticators, the list definition happens using either contextualizer or authorizer as key, followed by the required id. All mechanisms in this list are executed in the order, they are defined. If any of these fails, the entire pipeline fails, which leads to the execution of the error pipeline. This list is optional.\nFinalization Stage: List of finalizer references using finalizers as key, followed by the required finalizer id. All finalizers in this list are executed in the order they are defined. If any of these fail, the entire pipeline fails, which leads to the execution of the error pipeline. This list is optional. If a default rule is configured, and no finalizers are configured on a specific rule level, the finalizers from the default rule are used. If the default rule does not have any finalizers configured either, no finalization will take place.\nIn all cases, the used mechanism can be partially reconfigured if supported by the corresponding type. Configuration goes into the config properties. These reconfigurations are always local to the given rule. With other words, you can adjust your rule specific pipeline as you want without any side effects.\nExecution of an contextualizer, authorizer, or finalizer mechanisms can optionally happen conditionally by making use of a CEL expression in an if clause, which has access to the Subject and the Request objects. If the if clause is not present, the corresponding mechanism is always executed.\nExample 2. Complex pipeline # list of authenticators # defining the authentication stage - authenticator: foo - authenticator: bar config: subject: anon # ... any further required authenticator # list of authorizers and contextualizers in any order # defining the authentication stage - contextualizer: baz config: cache_ttl: 0s - authorizer: zab - contextualizer: foo if: Subject.ID != \u0026#34;anonymous\u0026#34; - contextualizer: bar - authorizer: foo if: Request.Method == \u0026#34;POST\u0026#34; config: expressions: - expression: | // some expression logic deviating from the // definition in the pipeline configuration. # ... any further required authorizer or contextualizer # list of finalizers # defining the finalization stage - finalizer: foo - finalizer: bar config: headers: - X-User-ID: {{ quote .ID }} # ... any further required finalizers This example uses\ntwo authenticators, with authenticator named bar being the fallback for the authenticator named foo. This fallback authenticator is obviously of type anonymous as it reconfigures the referenced prototype to use anon for subject id.\nmultiple contextualizers and authorizers, with first contextualizer having its cache disabled (cache_ttl set to 0s) and the last authorizer being of type cel as it reconfigures the referenced prototype to use a different authorization expression.\ntwo finalizers, with the second one being obviously of type header, as it defines a X-User-ID header set to the value of the subject id to be forwarded to the upstream service.\ncontextualizer foo is only executed if the authenticated subject is not anonymous.\nauthorizer foo is only executed if the request method is HTTP POST.\nError Pipeline Compared to the Authentication \u0026amp; Authorization Pipeline, the error pipeline is pretty simple. It is also a list of mechanism references, but all referenced types are error handler types. Thus, each entry in this list must have error_handler as key, followed by the ìd of the required error handler previously defined in the mechanism catalogue.\nExecution of the error handlers should happen conditionally by making use of a CEL expression in an if clause, which has access to the Error and the Request objects. Otherwise, the first error handler will be executed and the error pipeline will exit.\nAs with the authentication \u0026amp; authorization pipeline, partial reconfiguration of the used mechanisms is possible if supported by the corresponding type. The overrides are always local to the given rule as well.\nExample 3. Two error handlers - error_handler: foo if: # rule specific condition - error_handler: bar config: # rule specific config This example uses two error handlers, named foo and bar. bar will only be executed if foo \u0026#39;s error condition does not match. bar does also override the error handler configuration as required by the given rule.\n","description":"Regular rules allow definition and as such execution of arbitrary logic required by your upstream service. This page describes the available configuration options for a regular rule in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn the simplest case, a regular rule reuses mechanisms from the previously defined \u003ca href=\"/docs/mechanisms/catalogue/\"\u003ecatalogue\u003c/a\u003e in its pipelines. In more complex scenarios, a rule can reconfigure parts of the mechanisms being used. The specific parts that can be reconfigured or overridden depend on the mechanism itself and are described in the mechanism-specific documentation. Reconfiguration is always limited to the particular rule’s pipeline and does not affect other rules.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration\"\u003eConfiguration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA single regular rule consists of the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eid\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe unique identifier of the rule. It must be unique across all rules loaded by the same \u003ca href=\"/docs/rules/providers/\"\u003eRule Provider\u003c/a\u003e. To ensure uniqueness, it’s recommended to include the upstream service’s name and the rule’s purpose in the id. For example, \u003ccode\u003erule:my-service:public-api\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ematch\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eRuleMatcher\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines the matching criteria for a rule, with the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eroutes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eRouteMatcher array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies route conditions for matching the rule to incoming HTTP requests with each entry having the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epath\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"#_path_expression\"\u003ePath Expression\u003c/a\u003e describing the request path this rule should match. It supports both simple and free (named) wildcards.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epath_params\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003ePathParameterConditions\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAdditional conditions for the values captured by named wildcards in the path expression. Each entry supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the wildcard.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etype\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe type of expression used to match the captured wildcard’s value. The supported types are:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eglob\u003c/code\u003e: to use a \u003ca href=\"https://github.com/gobwas/glob\"\u003eglob expression\u003c/a\u003e to match the captured value (\u003ccode\u003e/\u003c/code\u003e is used as a delimiter, so \u003ccode\u003e*\u003c/code\u003e matches anything until the next \u003ccode\u003e/\u003c/code\u003e).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eregex\u003c/code\u003e to use a regular expression to match the captured value.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalue\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual expression based on the given \u003ccode\u003etype\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebacktracking_enabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables or disables backtracking when a request matches the path expressions but fails to meet additional matching criteria, like \u003ccode\u003epath_params\u003c/code\u003e, \u003ccode\u003ehosts\u003c/code\u003e, etc. This setting is inherited from the default rule and defaults to that rule’s setting. When enabled, the system will backtrack to attempt a match with a less specific rule (see \u003ca href=\"#_rule_matching_specificity_backtracking\"\u003eRule Matching Specificity \u0026amp; Backtracking\u003c/a\u003e for more details).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehosts\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eHostMatcher array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines a set of hosts to match against the HTTP Host header. Each entry has the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etype\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies the type of expression for matching the host, which can be one of:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eexact\u003c/code\u003e to match the host exactly\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eglob\u003c/code\u003e to use a \u003ca href=\"https://github.com/gobwas/glob\"\u003eglob expression\u003c/a\u003e which should be satisfied by the host of the incoming request (\u003ccode\u003e.\u003c/code\u003e is used as a delimiter, which means \u003ccode\u003e*\u003c/code\u003e will match anything until the next \u003ccode\u003e.\u003c/code\u003e).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eregex\u003c/code\u003e to use a regular expression which should be satisfied by the host of the incoming request.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalue\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual host expression based on the \u003ccode\u003etype\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escheme\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe expected HTTP scheme. If not specified, both http and https are accepted.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emethods\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies the allowed HTTP methods (\u003ccode\u003eGET\u003c/code\u003e, \u003ccode\u003ePOST\u003c/code\u003e, \u003ccode\u003ePATCH\u003c/code\u003e, etc). If not specified, all methods are allowed. To allow all methods except specific ones, use \u003ccode\u003eALL\u003c/code\u003e and prefix the methods to exclude with \u003ccode\u003e!\u003c/code\u003e. For example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# Methods list which effectively expands to all HTTP methods\u003c/span\u003e\n\u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eALL\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# Methods list consisting of all HTTP methods without `TRACE` and `OPTIONS`\u003c/span\u003e\n\u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eALL\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e!TRACE\u0026#34;\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e!OPTIONS\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_encoded_slashes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eControls how to handle URL-encoded slashes in request paths during matching and forwarding. Options include:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eoff\u003c/code\u003e\u003c/strong\u003e - Reject requests with encoded slashes (\u003ccode\u003e%2F\u003c/code\u003e). This is the default behavior.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eon\u003c/code\u003e\u003c/strong\u003e - Accept requests with encoded slashes decoding them to \u003ccode\u003e/\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eno_decode\u003c/code\u003e\u003c/strong\u003e - Accept requests with encoded slashes without touching them.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nHandling URL-encoded slashes may differ across the proxies in front of heimdall, heimdall, and the upstream service. Accepting requests with encoded slashes could, depending on your rules, lead to \u003ca href=\"https://cwe.mitre.org/data/definitions/436.html\"\u003eInterpretation Conflict\u003c/a\u003e vulnerabilities resulting in privilege escalations.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_to\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eRequestForwarder\u003c/em\u003e (mandatory in Proxy operation mode)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies where to forward proxied requests when heimdall is operating in proxy mode. The following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehost\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHost (and port) for forwarding the request. If no \u003ccode\u003erewrite\u003c/code\u003e property (see below) is defined, the original URL’s scheme, path, and other components are preserved. E.g. if the original request is \u003ccode\u003ehttps://mydomain.com/api/v1/something?foo=bar\u0026amp;bar=baz\u003c/code\u003e and the value of this property is set to \u003ccode\u003emy-backend:8080\u003c/code\u003e, the url used to forward the request to the upstream will be \u003ccode\u003ehttps://my-backend:8080/api/v1/something?foo=bar\u0026amp;bar=baz\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe \u003ccode\u003eHost\u003c/code\u003e header is not preserved when forwarding the request. To preserve it, use of the \u003ca href=\"/docs/mechanisms/finalizers/#_header\"\u003eheader finalizer\u003c/a\u003e in your \u003ccode\u003eexecute\u003c/code\u003e pipeline and set it accordingly. The example below demonstrates that.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003erewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eOriginalURLRewriter\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCan be used to rewrite further parts of the original URL before forwarding the request. If specified, at least one of the following supported (middleware) properties must be specified:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escheme\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies the URL scheme to use when forwarding the request. Defaults to the scheme used in the original request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUnless heimdall is started with the \u003ccode\u003e--insecure-skip-upstream-tls-enforcement\u003c/code\u003e flag, only \u003ccode\u003ehttps\u003c/code\u003e is allowed as the scheme.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003estrip_path_prefix\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis middleware strips the specified prefix from the original URL path before forwarding. E.g. if the path of the original url is \u003ccode\u003e/api/v1/something\u003c/code\u003e and the value of this property is set to \u003ccode\u003e/api/v1\u003c/code\u003e, the request to the upstream will have the url path set to \u003ccode\u003e/something\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eadd_path_prefix\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis middleware is applied after the execution of the \u003ccode\u003estrip_path_prefix\u003c/code\u003e middleware described above. If specified, heimdall will add the specified path prefix to the path used to forward the request to the upstream service. E.g. if the path of the original URL or the path resulting after the application of the \u003ccode\u003estrip_path_prefix\u003c/code\u003e middleware is \u003ccode\u003e/something\u003c/code\u003e and the value of this property is set to \u003ccode\u003e/my-backend\u003c/code\u003e, the request to the upstream will have the URL path set to \u003ccode\u003e/my-backend/something\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003estrip_query_parameters\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRemoves specified query parameters from the original URL before forwarding. E.g. if the query parameters part of the original URL is \u003ccode\u003efoo=bar\u0026amp;bar=baz\u003c/code\u003e and the value of this property is set to \u003ccode\u003e[\u0026#34;foo\u0026#34;]\u003c/code\u003e, the query part of the request to the upstream will be set to \u003ccode\u003ebar=baz\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexecute\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies the mechanisms used for authentication, authorization, contextualization, and finalization.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eon_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_error_pipeline\"\u003eError Pipeline\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies error handling mechanisms if the pipeline defined by the \u003ccode\u003eexecute\u003c/code\u003e property fails. Defaults to the error pipeline defined in the \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e if not specified.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. An example rule\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:foo:bar\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/some/:identifier/followed/by/**\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath_params\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eidentifier\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eglob\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e[a-z]\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-service.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePOST\u003c/span\u003e\n\u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebackend-a:8080\u003c/span\u003e\n \u003cspan class=\"na\"\u003erewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps\u003c/span\u003e\n \u003cspan class=\"na\"\u003estrip_path_prefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/api/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# the following just demonstrates how to make use of specific\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# mechanisms in the simplest possible form\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ezab\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# the following one demonstrates how to preserve the\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# Host header from the original request, while forwarding\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# it to the upstream service\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003epreserve-host\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# the config property can be omitted, if already configured\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# in the header finalizer mechanism\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eHost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Request.Header\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;Host\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e|\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\n\u003cspan class=\"na\"\u003eon_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_path_expression\"\u003ePath Expression\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePath expressions are used to match the incoming requests. When specifying these, you can make use of two types of wildcards:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003efree wildcard, which can be defined using \u003ccode\u003e*\u003c/code\u003e and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003esingle wildcard, which can be defined using \u003ccode\u003e:\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBoth can be named and unnamed, with named wildcards allowing accessing of the matched segments in the pipeline of the rule using the defined name as a key on the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_url_captures\"\u003e\u003ccode\u003eRequest.URL.Captures\u003c/code\u003e\u003c/a\u003e object. Unnamed free wildcard is defined as \u003ccode\u003e**\u003c/code\u003e and unnamed single wildcard is defined as \u003ccode\u003e:*\u003c/code\u003e. A named wildcard uses some identifier instead of the \u003ccode\u003e*\u003c/code\u003e, so like \u003ccode\u003e*name\u003c/code\u003e for free wildcard and \u003ccode\u003e:name\u003c/code\u003e for single wildcard.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe value of the path segment, respectively path segments available via the wildcard name is decoded. E.g. if you define the to be matched path in a rule as \u003ccode\u003e/file/:name\u003c/code\u003e, and the actual path of the request is \u003ccode\u003e/file/%5Bid%5D\u003c/code\u003e, you’ll get \u003ccode\u003e[id]\u003c/code\u003e when accessing the captured path segment via the \u003ccode\u003ename\u003c/code\u003e key. Not every path encoded value is decoded though. Decoding of encoded slashes happens only if \u003ccode\u003eallow_encoded_slashes\u003c/code\u003e was set to \u003ccode\u003eon\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere are some simple rules, which must be followed while using wildcards:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eOne can use as many single wildcards, as needed in any segment\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eA segment must start with \u003ccode\u003e:\u003c/code\u003e or \u003ccode\u003e*\u003c/code\u003e to define a wildcard\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNo segments are allowed after a free (named) wildcard\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf a regular segment must start with \u003ccode\u003e:\u003c/code\u003e or \u003ccode\u003e*\u003c/code\u003e, but should not be considered as a wildcard, it must be escaped with \u003ccode\u003e\\\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere some path examples:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/and/bananas\u003c/code\u003e - Matches exactly the given path\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/and/:something\u003c/code\u003e - Matches \u003ccode\u003e/apples/and/bananas\u003c/code\u003e, \u003ccode\u003e/apples/and/oranges\u003c/code\u003e and alike, but not \u003ccode\u003e/apples/and/bananas/andmore\u003c/code\u003e or \u003ccode\u003e/apples/or/bananas\u003c/code\u003e. Since a named single wildcard is used, the actual value of the path segment matched by \u003ccode\u003e:something\u003c/code\u003e can be accessed in the rule pipeline using \u003ccode\u003esomething\u003c/code\u003e as a key.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/:junction/:something\u003c/code\u003e - Similar to above. But will also match \u003ccode\u003e/apples/or/bananas\u003c/code\u003e in addition to \u003ccode\u003e/apples/and/bananas\u003c/code\u003e and \u003ccode\u003e/apples/and/oranges\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/and/some:thing\u003c/code\u003e - Matches exactly \u003ccode\u003e/apples/and/some:thing\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/and/some**\u003c/code\u003e - Matches exactly \u003ccode\u003e/apples/and/some**\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/**\u003c/code\u003e - Matches any path starting with \u003ccode\u003e/apples/\u003c/code\u003e, like \u003ccode\u003e/apples/and/bananas\u003c/code\u003e but not \u003ccode\u003e/apples/\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/*remainingpath\u003c/code\u003e - Same as above, but uses a named free wildcard\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/**/bananas\u003c/code\u003e - Is invalid, as there is a path segment after a free wildcard\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/\\*remainingpath\u003c/code\u003e - Matches exactly \u003ccode\u003e/apples/*remainingpath\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere is an example demonstrating the usage of a single named wildcard:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/files/:uuid/delete\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehosty.mchostface\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_check\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;user\u0026#34;: \u0026#34;{{ .Subject.ID }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;relation\u0026#34;: \u0026#34;can_delete\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;object\u0026#34;: \u0026#34;file:{{ .Request.URL.Captures.uuid }}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_rule_matching_specificity_backtracking\"\u003eRule Matching Specificity \u0026amp; Backtracking\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe implementation ensures that rules with more specific path expressions are matched first, regardless of their placement within a rule set. In fact, more specific rules are prioritized even when they are defined across different rule sets.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhen a path expression matches a request, any additional conditions specified in the rule’s matching criteria are evaluated. Only if these conditions are met will the rule’s pipeline be executed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf multiple rules share the same path expression and all their additional conditions match, the first matching rule will be applied. The matching order is determined by the sequence of rules in the rule set.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf no rule is matched, and backtracking is enabled, the process will backtrack to attempt a match with the next less specific rule. Backtracking will stop when:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ea less specific rule successfully matches (including evaluation of any additional conditions), or\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea less specific rule fails to match and does not permit backtracking.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following examples illustrate these principles:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine the following set of rules\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/files/**\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;pipeline definition\u0026gt;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule2\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/files/:team/:name\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath_params\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eteam\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eregex\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e(team1|team2)\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebacktracking_enabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;pipeline definition\u0026gt;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule3\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/files/team3/:name\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;pipeline definition\u0026gt;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe request to \u003ccode\u003e/files/team1/document.pdf\u003c/code\u003e will be matched by \u003ccode\u003erule2\u003c/code\u003e, as it is more specific than \u003ccode\u003erule1\u003c/code\u003e. Consequently, the pipeline for \u003ccode\u003erule2\u003c/code\u003e will be executed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe request to \u003ccode\u003e/files/team3/document.pdf\u003c/code\u003e will be matched by \u003ccode\u003erule3\u003c/code\u003e, which is more specific than both \u003ccode\u003erule1\u003c/code\u003e and \u003ccode\u003erule2\u003c/code\u003e. As a result, the corresponding pipeline will be executed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHowever, even though the request to \u003ccode\u003e/files/team4/document.pdf\u003c/code\u003e matches the path defined in \u003ccode\u003erule2\u003c/code\u003e, the regular expression \u003ccode\u003e(team1|team2)\u003c/code\u003e used in the \u003ccode\u003epath_params\u003c/code\u003e for the \u003ccode\u003eteam\u003c/code\u003e parameter will not match. Since \u003ccode\u003ebacktracking_enabled\u003c/code\u003e is set to \u003ccode\u003etrue\u003c/code\u003e, backtracking will occur, and the request will be matched by \u003ccode\u003erule1\u003c/code\u003e, with its pipeline then being executed.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs described in the \u003ca href=\"/docs/concepts/pipelines/\"\u003eConcepts\u003c/a\u003e section, this pipeline consists of mechanisms, previously configured in the \u003ca href=\"/docs/mechanisms/catalogue/\"\u003emechanisms catalogue\u003c/a\u003e, organized in stages as described below, with authentication stage (consisting of \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eauthenticators\u003c/a\u003e) being mandatory.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eAuthentication Stage:\u003c/strong\u003e List of \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eauthenticator\u003c/a\u003e references using \u003ccode\u003eauthenticator\u003c/code\u003e as key, followed by the required authenticator \u003ccode\u003eid\u003c/code\u003e. Authenticators following the first defined in the list are used by heimdall as fallback. That is, if first authenticator fails due to missing authentication data, second is executed, etc. By default, fallback is not used if an authenticator fails due to validation errors of the given authentication data. E.g. if an authenticator fails to validate the signature of a JWT token, the next authenticator in the list will not be executed. Instead, the entire pipeline will fail and lead to the execution of the \u003ca href=\"#_error_pipeline\"\u003eerror pipeline\u003c/a\u003e. This list is mandatory if no \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e is configured.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nSome authenticators use the same sources to get subject authentication object from. E.g. the \u003ccode\u003ejwt\u003c/code\u003e and the \u003ccode\u003eoauth2_introspection\u003c/code\u003e authenticators can retrieve tokens from the same places in the request. If such authenticators are used in the same pipeline, you should configure the more specific ones before the more general ones to have working default fallbacks. To stay with the above example, the \u003ccode\u003ejwt\u003c/code\u003e authenticator is more specific compared to \u003ccode\u003eoauth2_introspection\u003c/code\u003e, as it will be only executed, if the token is in a JWT format. In contrast to this, the \u003ccode\u003eoauth2_introspection\u003c/code\u003e authenticator is more general and does not care about the token format, thus will feel responsible for the request as soon as it finds a bearer token. You can however also make use of the \u003ccode\u003eallow_fallback_on_error\u003c/code\u003e configuration property and set it to \u003ccode\u003etrue\u003c/code\u003e. This will allow a fallback even if the verification of the credentials fail.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eAuthorization Stage:\u003c/strong\u003e List of \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003econtextualizer\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/authorizers/\"\u003eauthorizer\u003c/a\u003e references in any order (optional). Can also be mixed. As with authenticators, the list definition happens using either \u003ccode\u003econtextualizer\u003c/code\u003e or \u003ccode\u003eauthorizer\u003c/code\u003e as key, followed by the required \u003ccode\u003eid\u003c/code\u003e. All mechanisms in this list are executed in the order, they are defined. If any of these fails, the entire pipeline fails, which leads to the execution of the \u003ca href=\"#_error_pipeline\"\u003eerror pipeline\u003c/a\u003e. This list is optional.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eFinalization Stage:\u003c/strong\u003e List of \u003ca href=\"/docs/mechanisms/finalizers/\"\u003efinalizer\u003c/a\u003e references using \u003ccode\u003efinalizers\u003c/code\u003e as key, followed by the required finalizer \u003ccode\u003eid\u003c/code\u003e. All finalizers in this list are executed in the order they are defined. If any of these fail, the entire pipeline fails, which leads to the execution of the \u003ca href=\"#_error_pipeline\"\u003eerror pipeline\u003c/a\u003e. This list is optional. If a \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e is configured, and no \u003ccode\u003efinalizers\u003c/code\u003e are configured on a specific rule level, the \u003ccode\u003efinalizers\u003c/code\u003e from the default rule are used. If the default rule does not have any \u003ccode\u003efinalizers\u003c/code\u003e configured either, no finalization will take place.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn all cases, the used mechanism can be partially reconfigured if supported by the corresponding type. Configuration goes into the \u003ccode\u003econfig\u003c/code\u003e properties. These reconfigurations are always local to the given rule. With other words, you can adjust your rule specific pipeline as you want without any side effects.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExecution of an \u003ccode\u003econtextualizer\u003c/code\u003e, \u003ccode\u003eauthorizer\u003c/code\u003e, or \u003ccode\u003efinalizer\u003c/code\u003e mechanisms can optionally happen conditionally by making use of a \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e expression in an \u003ccode\u003eif\u003c/code\u003e clause, which has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects. If the \u003ccode\u003eif\u003c/code\u003e clause is not present, the corresponding mechanism is always executed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Complex pipeline\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# list of authenticators\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# defining the authentication stage\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# ... any further required authenticator\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# list of authorizers and contextualizers in any order\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# defining the authentication stage\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebaz\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e0s\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ezab\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSubject.ID != \u0026#34;anonymous\u0026#34;\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRequest.Method == \u0026#34;POST\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e// some expression logic deviating from the\u003c/span\u003e\n \u003cspan class=\"s\"\u003e// definition in the pipeline configuration.\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# ... any further required authorizer or contextualizer\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# list of finalizers\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# defining the finalization stage\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eX-User-ID\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{{\u003c/span\u003e \u003cspan class=\"nv\"\u003equote .ID\u003c/span\u003e \u003cspan class=\"pi\"\u003e}}\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# ... any further required finalizers\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example uses\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003etwo authenticators, with authenticator named \u003ccode\u003ebar\u003c/code\u003e being the fallback for the authenticator named \u003ccode\u003efoo\u003c/code\u003e. This fallback authenticator is obviously of type \u003ca href=\"/docs/mechanisms/authenticators/#_anonymous\"\u003eanonymous\u003c/a\u003e as it reconfigures the referenced prototype to use \u003ccode\u003eanon\u003c/code\u003e for subject id.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003emultiple contextualizers and authorizers, with first contextualizer having its cache disabled (\u003ccode\u003ecache_ttl\u003c/code\u003e set to 0s) and the last authorizer being of type \u003ca href=\"/docs/mechanisms/authorizers/#_local_cel\"\u003ecel\u003c/a\u003e as it reconfigures the referenced prototype to use a different authorization expression.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003etwo finalizers, with the second one being obviously of type \u003ca href=\"/docs/mechanisms/finalizers/#_header\"\u003eheader\u003c/a\u003e, as it defines a \u003ccode\u003eX-User-ID\u003c/code\u003e header set to the value of the subject id to be forwarded to the upstream service.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003econtextualizer \u003ccode\u003efoo\u003c/code\u003e is only executed if the authenticated subject is not anonymous.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eauthorizer \u003ccode\u003efoo\u003c/code\u003e is only executed if the request method is HTTP POST.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_error_pipeline\"\u003eError Pipeline\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCompared to the \u003ca href=\"#_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/a\u003e, the error pipeline is pretty simple. It is also a list of mechanism references, but all referenced types are \u003ca href=\"/docs/mechanisms/error_handlers/\"\u003eerror handler types\u003c/a\u003e. Thus, each entry in this list must have \u003ccode\u003eerror_handler\u003c/code\u003e as key, followed by the \u003ccode\u003eìd\u003c/code\u003e of the required error handler previously defined in the \u003ca href=\"/docs/mechanisms/catalogue/\"\u003emechanism catalogue\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExecution of the error handlers should happen conditionally by making use of a \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e expression in an \u003ccode\u003eif\u003c/code\u003e clause, which has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_error\"\u003e\u003ccode\u003eError\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects. Otherwise, the first error handler will be executed and the error pipeline will exit.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with the authentication \u0026amp; authorization pipeline, partial reconfiguration of the used mechanisms is possible if supported by the corresponding type. The overrides are always local to the given rule as well.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Two error handlers\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"c1\"\u003e# rule specific condition\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# rule specific config\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example uses two error handlers, named \u003ccode\u003efoo\u003c/code\u003e and \u003ccode\u003ebar\u003c/code\u003e. \u003ccode\u003ebar\u003c/code\u003e will only be executed if \u003ccode\u003efoo\u003c/code\u003e \u0026#39;s error condition does not match. \u003ccode\u003ebar\u003c/code\u003e does also override the error handler configuration as required by the given rule.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Rules"],"tags":null,"title":"Regular Rule","url":"/docs/rules/regular_rule/"},{"categories":null,"content":" Configuration The default rule can be configured using the default_rule property supporting the options shown below.\nThe default rule does not support all properties available in a regular rule.\nIt cannot be used to forward requests to an upstream service protected by heimdall. If heimdall is operating in reverse proxy mode, the default rule should be configured to reject requests. Otherwise, Heimdall will respond with an error.\nThe default rule also rejects requests containing encoded slashes in the URL path with a 400 Bad Request response. In a regular rule, this behavior can be configured.\nThe authentication stage cannot start with an insecure authenticator (i.e., authenticators that allow all requests to pass through). However, this enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-secure-default-rule-enforcement flag.\nbacktracking_enabled: boolean (optional)\nEnables or disables backtracking while matching the rules globally. Defaults to false.\nexecute: Authentication \u0026amp; Authorization Pipeline (mandatory)\nWhich mechanisms to use for authentication, authorization and finalization stages of the pipeline. At least the authentication stage with at least one authenticator must be defined. A specific rule (see also Regular Rule) can omit the definition of that stage, if it wants to reuse it from in the default rule. Same is true for other stages (See also Rule Inheritance).\non_error: Error Pipeline (optional)\nWhich error handler mechanisms to use if any of the mechanisms, defined in the execute property fail. Allows omitting the definition of error handlers in specific rules. As soon as a specific rule defines at least one error handler mechanism, all error handler mechanisms, defined in the default rule are ignored. If not specified, the default error handler is used.\nExample 1. Default rule configuration default_rule: execute: - authenticator: session_cookie_from_kratos_authn - authenticator: oauth2_introspect_token_from_keycloak_authn - authorizer: deny_all_requests_authz - finalizer: create_jwt on_error: - error_handler: authenticate_with_kratos_eh if: | type(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;session_cookie_from_kratos_authn\u0026#34; This example defines a default rule, with the authentication 6 authorization pipeline consisting of two authenticators, with session_cookie_from_kratos_authn being the first and oauth2_introspect_token_from_keycloak_authn being the fallback one (if the first one fails), a deny_all_requests_authz authorizer and the create_jwt finalizer. The error pipeline is configured to execute only the authenticate_with_kratos_eh error handler.\nObviously, the authentication \u0026amp; authorization pipeline (defined in the execute property) of this default rule will always result in an error due to deny_all_requests_authz. This way it is thought to provide secure defaults and let the upstream specific (regular) rules override at least the part dealing with authorization. Such an upstream specific rule could then look like follows:\nid: rule:my-service:protected-api match: routes: - path: /foo execute: - authorizer: allow_all_requests_authz Take a look at how on_error, as well as the authenticators and finalizers from the execute definition of the default rule are reused. Easy, no?\n","description":"Heimdall lets you not only define upstream service specific rules, it does also support a definition of an optional default rule, which, if defined, kicks in, if no other rule matches. This way you can ensure secure defaults by simultaneously reducing the amount of work while defining upstream service API specific rules.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration\"\u003eConfiguration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe default rule can be configured using the \u003ccode\u003edefault_rule\u003c/code\u003e property supporting the options shown below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe default rule does not support all properties available in a \u003ca href=\"/docs/rules/regular_rule/\"\u003eregular rule\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIt cannot be used to forward requests to an upstream service protected by heimdall. If heimdall is operating in reverse proxy mode, the default rule should be configured to reject requests. Otherwise, Heimdall will respond with an error.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe default rule also rejects requests containing encoded slashes in the URL path with a \u003ccode\u003e400 Bad Request\u003c/code\u003e response. In a regular rule, this behavior can be configured.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe authentication stage cannot start with an insecure authenticator (i.e., authenticators that allow all requests to pass through). However, this enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-secure-default-rule-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebacktracking_enabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables or disables backtracking while matching the rules globally. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexecute\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/rules/regular_rule/#_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhich mechanisms to use for authentication, authorization and finalization stages of the pipeline. At least the authentication stage with at least one \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eauthenticator\u003c/a\u003e must be defined. A specific rule (see also \u003ca href=\"/docs/rules/regular_rule/\"\u003eRegular Rule\u003c/a\u003e) can omit the definition of that stage, if it wants to reuse it from in the default rule. Same is true for other stages (See also \u003ca href=\"/docs/concepts/rules/#_default_rule_inheritance\"\u003eRule Inheritance\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eon_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/rules/regular_rule/#_error_pipeline\"\u003eError Pipeline\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhich error handler mechanisms to use if any of the mechanisms, defined in the \u003ccode\u003eexecute\u003c/code\u003e property fail. Allows omitting the definition of error handlers in specific rules. As soon as a specific rule defines at least one error handler mechanism, all error handler mechanisms, defined in the default rule are ignored. If not specified, the default error handler is used.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Default rule configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003edefault_rule\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esession_cookie_from_kratos_authn\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_introspect_token_from_keycloak_authn\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all_requests_authz\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003eon_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticate_with_kratos_eh\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;session_cookie_from_kratos_authn\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example defines a default rule, with the authentication 6 authorization pipeline consisting of two authenticators, with \u003ccode\u003esession_cookie_from_kratos_authn\u003c/code\u003e being the first and \u003ccode\u003eoauth2_introspect_token_from_keycloak_authn\u003c/code\u003e being the fallback one (if the first one fails), a \u003ccode\u003edeny_all_requests_authz\u003c/code\u003e authorizer and the \u003ccode\u003ecreate_jwt\u003c/code\u003e finalizer. The error pipeline is configured to execute only the \u003ccode\u003eauthenticate_with_kratos_eh\u003c/code\u003e error handler.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eObviously, the authentication \u0026amp; authorization pipeline (defined in the \u003ccode\u003eexecute\u003c/code\u003e property) of this default rule will always result in an error due to \u003ccode\u003edeny_all_requests_authz\u003c/code\u003e. This way it is thought to provide secure defaults and let the upstream specific (regular) rules override at least the part dealing with authorization. Such an upstream specific rule could then look like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:my-service:protected-api\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/foo\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow_all_requests_authz\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTake a look at how \u003ccode\u003eon_error\u003c/code\u003e, as well as the authenticators and finalizers from the \u003ccode\u003eexecute\u003c/code\u003e definition of the default rule are reused. Easy, no?\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Rules"],"tags":null,"title":"Default Rule","url":"/docs/rules/default_rule/"},{"categories":null,"content":" Depending on the configured provider, the rules can be then loaded from e.g. a plain old configuration file, residing in the local file system, or even from a Kubernetes environment as a custom resource. Thus, the structure and format of a rule set depends on the provider used to load it. As of today, there are two supported formats:\nas a regular JSON/YAML file, the so-called regular rule set, and\nas a kubernetes custom resource rule set, which is actually a YAML/JSON file as well, but adheres to corresponding kubernetes requirements.\nThe main difference is the internal structure. Both do however require the specification of a version and a list or rules.\nRegular Rule Set A regular rule set is a just a file with a list of rules and some additional meta information. Latter can be extended by a particular provider supporting that format.\nAvailable properties are:\nversion: string (mandatory)\nThe version schema of the rule set. The current version of heimdall supports only the version 1alpha4.\nname: string (optional)\nThe name of a rule set. Used only for logging purposes.\nrules: Rule Configuration array (mandatory)\nThe list of the actual rule definitions.\nExample 1. Rule set with two rules An imaginary rule set file defining two rules could look like shown below.\nversion: \u0026#34;1alpha4\u0026#34; name: my-rule-set rules: - id: rule:1 match: routes: - path: /** methods: [ \u0026#34;GET\u0026#34; ] scheme: https hosts: - type: exact value: my-service1.local execute: - authorizer: foobar - id: rule:2 match: routes: - path: /** scheme: https hosts: - type: exact value: my-service2.local methods: [ \u0026#34;GET\u0026#34; ] execute: - authorizer: barfoo Kubernetes Rule Set If you operate heimdall in kubernetes, most probably, you would like to make use of the RuleSet custom resource, which can be loaded by the kubernetes provider.\nConfiguration apiVersion: string (mandatory)\nThe api version of the custom resource definition, the given rule set is based on. The current version of heimdall supports only heimdall.dadrus.github.com/v1alpha4 version.\nkind: string (mandatory)\nThe custom resource kind. Must be set to RuleSet\nmetadata: map (optional)\nThe metadata, you would like to assign to the rule set, like the name of the rule set, labels, etc\nspec: map (mandatory)\nThe actual specification of the rule set. Following properties are possible, respectively required:\nauthClassName: string (optional)\nReferences the heimdall instance, which should use this RuleSet.\nrules: Rule Configuration array (mandatory)\nThe list of the actual rules.\nTo be able to deploy and make heimdall use the RuleSet custom resources, the corresponding CRD must be deployed. Otherwise, heimdall will not be able to monitor corresponding resources and emit error messages to the log.\nIf you have used the Helm Chart to install heimdall, this CRD is already installed. You can however install it also like this:\n$ kubectl apply -f https://raw.githubusercontent.com/dadrus/heimdall/main/charts/heimdall/crds/ruleset.yaml Example 2. Simple Example apiVersion: heimdall.dadrus.github.com/v1alpha4 kind: RuleSet metadata: name: \u0026#34;\u0026lt;some name\u0026gt;\u0026#34; spec: authClassName: \u0026#34;\u0026lt;optional auth_class reference (see above)\u0026gt; \u0026#34; rules: - id: \u0026#34;\u0026lt;identifier of a rule 1\u0026gt;\u0026#34; match: routes: - path: /foo/** scheme: https hosts: - type: exact value: 127.0.0.1:9090 execute: - authenticator: foo - authorizer: bar Resource Status In addition to configuration properties described above, a RuleSet resource has a status stanza, which provides information about the usage status as soon as a RuleSet has been loaded by at least one heimdall instance.\nBy making use of kubectl get -n \u0026lt;your namespace\u0026gt; rulesets.heimdall.dadrus.github.com you’ll get an overview of deployed RuleSet resources in a particular namespace, like e.g. shown below\nNAME ACTIVE IN AGE test-rules 2/2 32m The value 2/2 in ACTIVE IN means, \u0026lt;active in heimdall instances\u0026gt;/\u0026lt;matching instances\u0026gt;. With\n\u0026#34;matching instances\u0026#34; being those heimdall instances, which auth_class matches the authClassName in the RuleSet and\n\u0026#34;active in heimdall instances\u0026#34; are those from the \u0026#34;matching instances\u0026#34;, which were able to load the RuleSet.\nIn addition, you can also get further information about the executed reconciliations by the deployed heimdall instances by taking a look at the .status.conditions field. The reconciliation status of matching instances is present there. That also means, if there were errors while loading the RuleSet, these are present in this condition list\nE.g.\n$ kubectl describe -n test rulesets.heimdall.dadrus.github.com test-rules Name: test-rules Namespace: test ... Status: Conditions: Last Transition Time: 2023-11-08T21:55:36Z Message: heimdall-6fb66c47bc-kwqqn instance successfully loaded RuleSet Observed Generation: 1 Reason: RuleSetActive Status: True Type: heimdall-6fb66c47bc-kwqqn/Reconciliation Last Transition Time: 2023-11-08T21:55:36Z Message: heimdall-6fb66c47bc-l7skn instance successfully loaded RuleSet Observed Generation: 1 Reason: RuleSetActive Status: True Type: heimdall-6fb66c47bc-l7skn/Reconciliation Active In: 2/2 Events: \u0026lt;none\u0026gt; ","description":"Rule Sets organize rules, allowing versioning of such and loading by providers.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDepending on the configured provider, the rules can be then loaded from e.g. a plain old configuration file, residing in the local file system, or even from a Kubernetes environment as a custom resource. Thus, the structure and format of a rule set depends on the \u003ca href=\"/docs/rules/providers/\"\u003eprovider\u003c/a\u003e used to load it. As of today, there are two supported formats:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eas a regular JSON/YAML file, the so-called \u003ca href=\"#_regular_rule_set\"\u003eregular rule set\u003c/a\u003e, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eas a kubernetes \u003ca href=\"#_kubernetes_rule_set\"\u003ecustom resource rule set\u003c/a\u003e, which is actually a YAML/JSON file as well, but adheres to corresponding kubernetes requirements.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe main difference is the internal structure. Both do however require the specification of a version and a list or rules.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_regular_rule_set\"\u003eRegular Rule Set\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA regular rule set is a just a file with a list of rules and some additional meta information. Latter can be extended by a particular \u003ca href=\"/docs/rules/providers/\"\u003eprovider\u003c/a\u003e supporting that format.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAvailable properties are:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eversion\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe version schema of the rule set. The current version of heimdall supports only the version \u003ccode\u003e1alpha4\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of a rule set. Used only for logging purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003erules\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/rules/regular_rule/#_configuration\"\u003eRule Configuration\u003c/a\u003e array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe list of the actual rule definitions.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Rule set with two rules\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAn imaginary rule set file defining two rules could look like shown below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-rule-set\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/**\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eGET\u0026#34;\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-service1.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:2\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/**\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-service2.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eGET\u0026#34;\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebarfoo\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_kubernetes_rule_set\"\u003eKubernetes Rule Set\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you operate heimdall in kubernetes, most probably, you would like to make use of the \u003ccode\u003eRuleSet\u003c/code\u003e custom resource, which can be loaded by the \u003ca href=\"/docs/rules/providers/#_kubernetes\"\u003ekubernetes provider\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eapiVersion\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe api version of the custom resource definition, the given rule set is based on. The current version of heimdall supports only \u003ccode\u003eheimdall.dadrus.github.com/v1alpha4\u003c/code\u003e version.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ekind\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe custom resource kind. Must be set to \u003ccode\u003eRuleSet\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emetadata\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emap\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe metadata, you would like to assign to the rule set, like the name of the rule set, labels, etc\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003espec\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emap\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual specification of the rule set. Following properties are possible, respectively required:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauthClassName\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eReferences the heimdall instance, which should use this \u003ccode\u003eRuleSet\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003erules\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/rules/regular_rule/#_configuration\"\u003eRule Configuration\u003c/a\u003e array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe list of the actual rules.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo be able to deploy and make heimdall use the \u003ccode\u003eRuleSet\u003c/code\u003e custom resources, the corresponding CRD must be deployed. Otherwise, heimdall will not be able to monitor corresponding resources and emit error messages to the log.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you have used the \u003ca href=\"/docs/getting_started/installation/#_helm_chart\"\u003eHelm Chart\u003c/a\u003e to install heimdall, this CRD is already installed. You can however install it also like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ekubectl apply \u003cspan class=\"nt\"\u003e-f\u003c/span\u003e https://raw.githubusercontent.com/dadrus/heimdall/main/charts/heimdall/crds/ruleset.yaml\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Simple Example\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall.dadrus.github.com/v1alpha4\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRuleSet\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026lt;some\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthClassName\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026lt;optional\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eauth_class\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ereference\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e(see\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eabove)\u0026gt;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026lt;identifier\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eof\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ea\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003erule\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e1\u0026gt;\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/foo/**\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1:9090\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_resource_status\"\u003eResource Status\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition to configuration properties described above, a \u003ccode\u003eRuleSet\u003c/code\u003e resource has a \u003ccode\u003estatus\u003c/code\u003e stanza, which provides information about the usage status as soon as a \u003ccode\u003eRuleSet\u003c/code\u003e has been loaded by at least one heimdall instance.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of \u003ccode\u003ekubectl get -n \u0026lt;your namespace\u0026gt; rulesets.heimdall.dadrus.github.com\u003c/code\u003e you’ll get an overview of deployed \u003ccode\u003eRuleSet\u003c/code\u003e resources in a particular namespace, like e.g. shown below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eNAME ACTIVE IN AGE\ntest-rules 2/2 32m\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe value \u003ccode\u003e2/2\u003c/code\u003e in \u003ccode\u003eACTIVE IN\u003c/code\u003e means, \u0026lt;active in heimdall instances\u0026gt;/\u0026lt;matching instances\u0026gt;. With\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u0026#34;matching instances\u0026#34; being those heimdall instances, which \u003ccode\u003eauth_class\u003c/code\u003e matches the \u003ccode\u003eauthClassName\u003c/code\u003e in the \u003ccode\u003eRuleSet\u003c/code\u003e and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u0026#34;active in heimdall instances\u0026#34; are those from the \u0026#34;matching instances\u0026#34;, which were able to load the \u003ccode\u003eRuleSet\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition, you can also get further information about the executed reconciliations by the deployed heimdall instances by taking a look at the \u003ccode\u003e.status.conditions\u003c/code\u003e field. The reconciliation status of matching instances is present there. That also means, if there were errors while loading the \u003ccode\u003eRuleSet\u003c/code\u003e, these are present in this condition list\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ekubectl describe \u003cspan class=\"nt\"\u003e-n\u003c/span\u003e \u003cspan class=\"nb\"\u003etest \u003c/span\u003erulesets.heimdall.dadrus.github.com test-rules\n\nName: test-rules\nNamespace: \u003cspan class=\"nb\"\u003etest\u003c/span\u003e\n...\nStatus:\n Conditions:\n Last Transition Time: 2023-11-08T21:55:36Z\n Message: heimdall-6fb66c47bc-kwqqn instance successfully loaded RuleSet\n Observed Generation: 1\n Reason: RuleSetActive\n Status: True\n Type: heimdall-6fb66c47bc-kwqqn/Reconciliation\n Last Transition Time: 2023-11-08T21:55:36Z\n Message: heimdall-6fb66c47bc-l7skn instance successfully loaded RuleSet\n Observed Generation: 1\n Reason: RuleSetActive\n Status: True\n Type: heimdall-6fb66c47bc-l7skn/Reconciliation\n Active In: 2/2\n Events: \u0026lt;none\u0026gt;\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Rules"],"tags":null,"title":"Rule Sets","url":"/docs/rules/rule_sets/"},{"categories":null,"content":" Providers allow definition of sources to load the rule sets from. These make heimdall’s behavior dynamic. All providers, you want to enable for a heimdall instance must be configured within the providers section of heimdall’s configuration.\nBelow, you can find the description and configuration options for currently supported providers.\nFilesystem The filesystem provider allows loading of regular rule sets in JSON or YAML format from a file system.\nConfiguration The configuration of this provider goes into the file_system property. This provider is handy for e.g. starting playing around with heimdall, e.g. locally, or using a container runtime, as well as if your deployment strategy considers deploying a heimdall instance as a Side-Car for each of your services.\nFollowing configuration options are supported:\nsrc: string (mandatory)\nCan either be a single file, containing a rule set, or a directory with files, each containing a rule set.\nwatch: boolean (optional)\nWhether the configured src should be watched for updates. Defaults to false. If the src has been configured to a single file, the provider will watch for changes in that file. Otherwise, if the src has been configured to a directory, the provider will watch for files appearing and disappearing in this directory, as well as for changes in each particular file in this directory. Recursive lookup is not supported. That is, if the configured directory contains further directories, these, as well as their contents are ignored.\nenv_vars_enabled: boolean (optional)\nWhether to enable environment variables access in the rule set files. Defaults to false. If set to true, environment variables usage using Bash syntax is possible as with the static configuration.\nAll environment variables, used in the rule set files must be known in advance to the heimdall process (when it starts). In addition, the usage of that functionality might lead to security issues. If an adversary is somehow able to add new or update existing rule sets, it would be theoretically able exfiltrating environment variables available to the heimdall process by crafting contextualizers or authorizers, which would forward the corresponding values to a controlled service. So, use with caution, disable the watching of rule set updates and try to avoid! Example 1. Rule set making use of environment variables version: \u0026#34;1alpha4\u0026#34; name: my-rule-set rules: - id: rule:1 match: routes: - path: /** hosts: - type: exact value: my-service1.local methods: [ \u0026#34;GET\u0026#34; ] forward_to: host: ${UPSTREAM_HOST:=\u0026#34;default-backend:8080\u0026#34;} execute: - authorizer: foobar Examples Example 2. Load rule sets from the files residing in the /path/to/rules/dir directory and watch for changes. file_system: src: /path/to/rules/dir watch: true Example 3. Load rule sets from the /path/to/rules.yaml file without watching it for changes. file_system: src: /path/to/rules.yaml HTTP Endpoint This provider allows loading of regular rule sets in JSON or YAML format from any remote endpoint accessible via HTTP(s). The format selection happens based on the Content-Type set in the response from the endpoint, which must be either application/yaml or application/json, otherwise an error is logged and the response from the endpoint is ignored.\nThe loading and removal of rules happens as follows:\nif the response status code is an HTTP 200 OK and contains a rule sets in a known format (see above), the corresponding rules are loaded (if the definitions are valid)\nin case of network issues, like dns errors, timeouts and alike, the rule sets previously received from the corresponding endpoints are preserved.\nin any other case related to network communication (e.g. not 200 status code, empty response body, unsupported format, etc.), the corresponding rules are removed if previously loaded.\nConfiguration The configuration of this provider goes into the http_endpoint property. In contrast to the Filesystem provider, it can be configured with as many endpoints to load rule sets from as required for the particular use case.\nFollowing configuration options are supported:\nwatch_interval: Duration (optional)\nWhether the configured endpoints should be polled for updates. Defaults to 0s (polling disabled).\nendpoints: Endpoint array (mandatory)\nEach entry of that array supports all the properties defined by Endpoint, except method, which is always GET. As with the Endpoint type, at least the url must be configured.\nHTTP caching according to RFC 7234 is enabled by default. It can be disabled on the particular endpoint by setting http_cache.enabled to false. Examples Example 4. Minimal possible configuration Here the provider is configured to load a rule set from one endpoint without polling it for changes.\nhttp_endpoint: endpoints: - url: https://foo.bar/ruleset1 Example 5. Load rule sets from remote endpoints and watch for changes. Here, the provider is configured to poll the two defined rule set endpoints for changes every 5 minutes.\nThe configuration for both endpoints instructs heimdall to disable HTTP caching. The configuration of the second endpoint uses a couple of additional properties. One to ensure the communication to that endpoint is more resilient by setting the retry options and since this endpoint is protected by an API key, it defines the corresponding options as well.\nhttp_endpoint: watch_interval: 5m endpoints: - url: https://foo.bar/ruleset1 http_cache: enabled: false - url: https://foo.bar/ruleset2 http_cache: enabled: false retry: give_up_after: 5s max_delay: 250ms auth: type: api_key config: name: X-Api-Key value: super-secret in: header Cloud Blob This provider allows loading of regular rule sets from cloud blobs, like AWS S3 buckets, Google Cloud Storage, Azure Blobs, or other API compatible implementations and supports rule sets in YAML, as well as in JSON format. The format selection happens based on the Content-Type set in the metadata of the loaded blob, which must be either application/yaml or application/json, otherwise an error is logged and the blob is ignored.\nThe loading and removal of rules happens as follows:\nif the response status code is an HTTP 200 OK and contains a rule set in a known format (see above), the corresponding rules are loaded (if the definitions are valid)\nin case of network issues, like dns errors, timeouts and alike, the rule sets previously received from the corresponding buckets are preserved.\nin any other case like, not 200 status code, empty response body, unsupported format, etc, the corresponding rules are removed if previously loaded.\nConfiguration The configuration of this provider goes into the cloud_blob property. As with HTTP Endpoint provider, it can be configured with as many buckets/blobs to load rule sets from as required for the particular use case.\nFollowing configuration options are supported:\nwatch_interval: Duration (optional)\nWhether the configured buckets should be polled for updates. Defaults to 0s (polling disabled).\nbuckets: BlobReference array (mandatory)\nEach BlobReference entry in that array supports the following properties:\nurl: string (mandatory)\nThe actual url to the bucket or to a specific blob in the bucket.\nprefix: string (optional)\nIndicates that only blobs with a key starting with this prefix should be retrieved\nThe differentiation which storage is used is based on the URL scheme. These are:\ns3 for AWS S3 buckets\ngs for Google Cloud Storage and\nazblob for Azure Blob Storage\nOther API compatible storage services, like Minio, Ceph, SeaweedFS, etc. can be used as well. The corresponding and other options can be found in the Go CDK Blob documentation, the implementation of this provider is based on.\nThe communication to the storage services requires an active session to the corresponding cloud provider. The session information is taken from the vendor specific environment variables, respectively configuration. See AWS Session, GC Application Default Credentials and Azure Storage Access for more information. Examples Example 6. Minimal possible configuration Here the provider is configured to load rule sets from all blobs stored on the Google Cloud Storage bucket named \u0026#34;my-bucket\u0026#34; without polling for changes.\ncloud_blob: buckets: - url: gs://my-bucket Example 7. Load rule sets from AWS S3 buckets and watch for changes. cloud_blob: watch_interval: 2m buckets: - url: gs://my-bucket prefix: service1 - url: gs://my-bucket prefix: service2 - url: s3://my-bucket/my-rule-set?region=us-west-1 Here, the provider is configured to poll multiple buckets with rule sets for changes every 2 minutes.\nThe first two bucket reference configurations reference actually the same bucket on Google Cloud Storage, but different blobs based on the configured blob prefix. The first one will let heimdall loading only those blobs, which start with service1, the second only those, which start with service2.\nThe last one instructs heimdall to load rule set from a specific blob, namely a blob named my-rule-set, which resides on the my-bucket AWS S3 bucket, which is located in the us-west-1 AWS region.\nKubernetes This provider is only supported if heimdall is running within Kubernetes and allows usage (validation and loading) of RuleSet custom resources deployed to the same Kubernetes environment.\nConfiguration The configuration of this provider goes into the kubernetes property and supports the following configuration options:\nauth_class: string (optional)\nBy making use of this property, you can specify which rule sets should be used by this particular heimdall instance. If specified, heimdall will consider the value of the authClassName attribute of each RuleSet resource deployed to the cluster and validate, respectively load only those rules, which authClassName values matching the value of auth_class. If not set all RuleSet resources will be used.\ntls: TLS (optional)\nIf configured, heimdall will start and expose a validating admission controller service on port 4458 listening on all interfaces. This service allows integration with the Kubernetes API server enabling validation of the applied RuleSet resources before these are made available to heimdall for loading. This way you will get a direct feedback about issues without the need to look into heimdall logs if a RuleSet resource could not be loaded (See also API documentation for more details).\nTo let the Kubernetes API server use the admission controller, there is a need for a properly configured ValidatingWebhookConfiguration. The Helm Chart shipped with heimdall does this automatically as soon as this property is configured. It does however need a caBundle to be set or injected. Otherwise, the Kubernetes API server won’t trust the configured TLS certificate and won’t use the endpoint.\nSince multiple heimdall deployments with different configured auth_class names can coexist, RuleSet resources with mismatching authClassName will be ignored by a particular deployment. In addition, Kubernetes API server validation requests for mismatching rule sets result in a successful response. This behavior is required as otherwise, as soon as the API server receives even a single failed validation response, the affected RuleSet resource will be discarded and not made available for loading to any of the available heimdall deployments.\nThat also means, if there is no heimdall deployment feeling responsible for the given RuleSet resource (due to authClassName - auth_class mismatch), the affected RuleSet resource will be silently ignored.\nExamples Example 8. Minimal possible configuration Here, the provider is just enabled. Since no auth_class is configured, it will load all RuleSet resources deployed to the Kubernetes environment.\nkubernetes: {} Example 9. Configuration with auth_class set Here, the provider is configured to consider only those RuleSet resources, which authClassName is set to foo.\nkubernetes: auth_class: foo Example 10. Configuration with auth_class set and enabled validating admission controller As with the previous example, the provider is configured to consider only those RuleSet resources, which authClassName is set to foo. The admission controller is enabled as well and will validate RuleSet resources before these are made available for loading.\nkubernetes: auth_class: foo tls: # below is the minimal required configuration key_store: path: /path/to/file.pem This provider requires a RuleSet CRD being deployed, otherwise heimdall will not be able to monitor corresponding resources and emit error messages to the log.\nIf you have used the Helm Chart to install heimdall, this CRD is already installed. You can however install it also like this:\n$ kubectl apply -f https://raw.githubusercontent.com/dadrus/heimdall/main/charts/heimdall/crds/ruleset.yaml ","description":"Rule providers manage rules in heimdall. They load, reload or remove rules when new rule sets appear, changes are detected, or rule sets are deleted.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eProviders allow definition of sources to load the \u003ca href=\"/docs/rules/rule_sets/\"\u003erule sets\u003c/a\u003e from. These make heimdall’s behavior dynamic. All providers, you want to enable for a heimdall instance must be configured within the \u003ccode\u003eproviders\u003c/code\u003e section of heimdall’s configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBelow, you can find the description and configuration options for currently supported providers.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_filesystem\"\u003eFilesystem\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe filesystem provider allows loading of \u003ca href=\"/docs/rules/rule_sets/#_regular_rule_set\"\u003eregular rule sets\u003c/a\u003e in JSON or YAML format from a file system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this provider goes into the \u003ccode\u003efile_system\u003c/code\u003e property. This provider is handy for e.g. starting playing around with heimdall, e.g. locally, or using a container runtime, as well as if your deployment strategy considers deploying a heimdall instance as a Side-Car for each of your services.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing configuration options are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esrc\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCan either be a single file, containing a rule set, or a directory with files, each containing a rule set.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewatch\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhether the configured \u003ccode\u003esrc\u003c/code\u003e should be watched for updates. Defaults to \u003ccode\u003efalse\u003c/code\u003e. If the \u003ccode\u003esrc\u003c/code\u003e has been configured to a single file, the provider will watch for changes in that file. Otherwise, if the \u003ccode\u003esrc\u003c/code\u003e has been configured to a directory, the provider will watch for files appearing and disappearing in this directory, as well as for changes in each particular file in this directory. Recursive lookup is not supported. That is, if the configured directory contains further directories, these, as well as their contents are ignored.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eenv_vars_enabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhether to enable environment variables access in the rule set files. Defaults to \u003ccode\u003efalse\u003c/code\u003e. If set to \u003ccode\u003etrue\u003c/code\u003e, environment variables usage using Bash syntax is possible as with the \u003ca href=\"/docs/operations/configuration/#_configuration_file\"\u003estatic configuration\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAll environment variables, used in the rule set files must be known in advance to the heimdall process (when it starts). In addition, the usage of that functionality might lead to security issues. If an adversary is somehow able to add new or update existing rule sets, it would be theoretically able exfiltrating environment variables available to the heimdall process by crafting contextualizers or authorizers, which would forward the corresponding values to a controlled service. So, use with caution, disable the watching of rule set updates and try to avoid!\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Rule set making use of environment variables\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-rule-set\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/**\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-service1.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eGET\u0026#34;\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${UPSTREAM_HOST:=\u0026#34;default-backend:8080\u0026#34;}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_examples\"\u003eExamples\u003c/h3\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Load rule sets from the files residing in the \u003ccode\u003e/path/to/rules/dir\u003c/code\u003e directory and watch for changes.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/rules/dir\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Load rule sets from the \u003ccode\u003e/path/to/rules.yaml\u003c/code\u003e file without watching it for changes.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/rules.yaml\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_http_endpoint\"\u003eHTTP Endpoint\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis provider allows loading of \u003ca href=\"/docs/rules/rule_sets/#_regular_rule_set\"\u003eregular rule sets\u003c/a\u003e in JSON or YAML format from any remote endpoint accessible via HTTP(s). The format selection happens based on the \u003ccode\u003eContent-Type\u003c/code\u003e set in the response from the endpoint, which must be either \u003ccode\u003eapplication/yaml\u003c/code\u003e or \u003ccode\u003eapplication/json\u003c/code\u003e, otherwise an error is logged and the response from the endpoint is ignored.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe loading and removal of rules happens as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eif the response status code is an HTTP 200 OK and contains a rule sets in a known format (see above), the corresponding rules are loaded (if the definitions are valid)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ein case of network issues, like dns errors, timeouts and alike, the rule sets previously received from the corresponding endpoints are preserved.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ein any other case related to network communication (e.g. not 200 status code, empty response body, unsupported format, etc.), the corresponding rules are removed if previously loaded.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_2\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this provider goes into the \u003ccode\u003ehttp_endpoint\u003c/code\u003e property. In contrast to the \u003ca href=\"#_filesystem\"\u003eFilesystem\u003c/a\u003e provider, it can be configured with as many endpoints to load rule sets from as required for the particular use case.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing configuration options are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewatch_interval\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhether the configured \u003ccode\u003eendpoints\u003c/code\u003e should be polled for updates. Defaults to \u003ccode\u003e0s\u003c/code\u003e (polling disabled).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eendpoints\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach entry of that array supports all the properties defined by \u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e, except \u003ccode\u003emethod\u003c/code\u003e, which is always \u003ccode\u003eGET\u003c/code\u003e. As with the \u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e type, at least the \u003ccode\u003eurl\u003c/code\u003e must be configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nHTTP caching according to \u003ca href=\"https://www.rfc-editor.org/rfc/rfc7234\"\u003eRFC 7234\u003c/a\u003e is enabled by default. It can be disabled on the particular endpoint by setting \u003ccode\u003ehttp_cache.enabled\u003c/code\u003e to \u003ccode\u003efalse\u003c/code\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_examples_2\"\u003eExamples\u003c/h3\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Minimal possible configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere the provider is configured to load a rule set from one endpoint without polling it for changes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ehttp_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar/ruleset1\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Load rule sets from remote endpoints and watch for changes.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, the provider is configured to poll the two defined rule set endpoints for changes every 5 minutes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration for both endpoints instructs heimdall to disable HTTP caching. The configuration of the second endpoint uses a couple of additional properties. One to ensure the communication to that endpoint is more resilient by setting the \u003ccode\u003eretry\u003c/code\u003e options and since this endpoint is protected by an API key, it defines the corresponding options as well.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ehttp_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch_interval\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar/ruleset1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar/ruleset2\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"na\"\u003eretry\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e250ms\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Api-Key\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esuper-secret\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cloud_blob\"\u003eCloud Blob\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis provider allows loading of \u003ca href=\"/docs/rules/rule_sets/#_regular_rule_set\"\u003eregular rule sets\u003c/a\u003e from cloud blobs, like AWS S3 buckets, Google Cloud Storage, Azure Blobs, or other API compatible implementations and supports rule sets in YAML, as well as in JSON format. The format selection happens based on the \u003ccode\u003eContent-Type\u003c/code\u003e set in the metadata of the loaded blob, which must be either \u003ccode\u003eapplication/yaml\u003c/code\u003e or \u003ccode\u003eapplication/json\u003c/code\u003e, otherwise an error is logged and the blob is ignored.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe loading and removal of rules happens as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eif the response status code is an HTTP 200 OK and contains a rule set in a known format (see above), the corresponding rules are loaded (if the definitions are valid)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ein case of network issues, like dns errors, timeouts and alike, the rule sets previously received from the corresponding buckets are preserved.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ein any other case like, not 200 status code, empty response body, unsupported format, etc, the corresponding rules are removed if previously loaded.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_3\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this provider goes into the \u003ccode\u003ecloud_blob\u003c/code\u003e property. As with \u003ca href=\"#_http_endpoint\"\u003eHTTP Endpoint\u003c/a\u003e provider, it can be configured with as many buckets/blobs to load rule sets from as required for the particular use case.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing configuration options are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewatch_interval\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhether the configured \u003ccode\u003ebuckets\u003c/code\u003e should be polled for updates. Defaults to \u003ccode\u003e0s\u003c/code\u003e (polling disabled).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebuckets\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eBlobReference array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach \u003cem\u003eBlobReference\u003c/em\u003e entry in that array supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eurl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual url to the bucket or to a specific blob in the bucket.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eprefix\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIndicates that only blobs with a key starting with this prefix should be retrieved\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe differentiation which storage is used is based on the URL scheme. These are:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003es3\u003c/code\u003e for \u003ca href=\"https://aws.amazon.com/s3/\"\u003eAWS S3\u003c/a\u003e buckets\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003egs\u003c/code\u003e for \u003ca href=\"https://cloud.google.com/storage/\"\u003eGoogle Cloud Storage\u003c/a\u003e and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eazblob\u003c/code\u003e for \u003ca href=\"https://azure.microsoft.com/en-us/services/storage/blobs/\"\u003eAzure Blob Storage\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOther API compatible storage services, like \u003ca href=\"https://www.minio.io/\"\u003eMinio\u003c/a\u003e, \u003ca href=\"https://ceph.com/\"\u003eCeph\u003c/a\u003e, \u003ca href=\"https://github.com/chrislusf/seaweedfs\"\u003eSeaweedFS\u003c/a\u003e, etc. can be used as well. The corresponding and other options can be found in the \u003ca href=\"https://gocloud.dev/howto/blob/\"\u003eGo CDK Blob\u003c/a\u003e documentation, the implementation of this provider is based on.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe communication to the storage services requires an active session to the corresponding cloud provider. The session information is taken from the vendor specific environment variables, respectively configuration. See \u003ca href=\"https://docs.aws.amazon.com/sdk-for-go/api/aws/session/\"\u003eAWS Session\u003c/a\u003e, \u003ca href=\"https://cloud.google.com/docs/authentication/application-default-credentials\"\u003eGC Application Default Credentials\u003c/a\u003e and \u003ca href=\"https://learn.microsoft.com/en-us/azure/storage/common/authorize-data-access?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json\"\u003eAzure Storage Access\u003c/a\u003e for more information.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_examples_3\"\u003eExamples\u003c/h3\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 6. Minimal possible configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere the provider is configured to load rule sets from all blobs stored on the Google Cloud Storage bucket named \u0026#34;my-bucket\u0026#34; without polling for changes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecloud_blob\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuckets\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egs://my-bucket\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 7. Load rule sets from AWS S3 buckets and watch for changes.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecloud_blob\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch_interval\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2m\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuckets\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egs://my-bucket\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservice1\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egs://my-bucket\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservice2\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003es3://my-bucket/my-rule-set?region=us-west-1\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, the provider is configured to poll multiple buckets with rule sets for changes every 2 minutes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe first two bucket reference configurations reference actually the same bucket on Google Cloud Storage, but different blobs based on the configured blob prefix. The first one will let heimdall loading only those blobs, which start with \u003ccode\u003eservice1\u003c/code\u003e, the second only those, which start with \u003ccode\u003eservice2\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe last one instructs heimdall to load rule set from a specific blob, namely a blob named \u003ccode\u003emy-rule-set\u003c/code\u003e, which resides on the \u003ccode\u003emy-bucket\u003c/code\u003e AWS S3 bucket, which is located in the \u003ccode\u003eus-west-1\u003c/code\u003e AWS region.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_kubernetes\"\u003eKubernetes\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis provider is only supported if heimdall is running within Kubernetes and allows usage (validation and loading) of \u003ca href=\"/docs/rules/rule_sets/#_kubernetes_rule_set\"\u003e\u003ccode\u003eRuleSet\u003c/code\u003e custom resources\u003c/a\u003e deployed to the same Kubernetes environment.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_4\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this provider goes into the \u003ccode\u003ekubernetes\u003c/code\u003e property and supports the following configuration options:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauth_class\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can specify which rule sets should be used by this particular heimdall instance. If specified, heimdall will consider the value of the \u003ccode\u003eauthClassName\u003c/code\u003e attribute of each \u003ccode\u003eRuleSet\u003c/code\u003e resource deployed to the cluster and validate, respectively load only those rules, which \u003ccode\u003eauthClassName\u003c/code\u003e values matching the value of \u003ccode\u003eauth_class\u003c/code\u003e. If not set all \u003ccode\u003eRuleSet\u003c/code\u003e resources will be used.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etls\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_tls\"\u003eTLS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf configured, heimdall will start and expose a validating admission controller service on port \u003ccode\u003e4458\u003c/code\u003e listening on all interfaces. This service allows integration with the Kubernetes API server enabling validation of the applied \u003ccode\u003eRuleSet\u003c/code\u003e resources before these are made available to heimdall for loading. This way you will get a direct feedback about issues without the need to look into heimdall logs if a \u003ccode\u003eRuleSet\u003c/code\u003e resource could not be loaded (See also \u003ca href=\"/openapi/#tag/Validating-Admission-Controller\"\u003eAPI\u003c/a\u003e documentation for more details).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo let the Kubernetes API server use the admission controller, there is a need for a properly configured \u003ca href=\"https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#deploy-the-admission-webhook-service\"\u003e\u003ccode\u003eValidatingWebhookConfiguration\u003c/code\u003e\u003c/a\u003e. The \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/charts/heimdall\"\u003eHelm Chart\u003c/a\u003e shipped with heimdall does this automatically as soon as this property is configured. It does however need a \u003ccode\u003ecaBundle\u003c/code\u003e to be set or injected. Otherwise, the Kubernetes API server won’t trust the configured TLS certificate and won’t use the endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince multiple heimdall deployments with different configured \u003ccode\u003eauth_class\u003c/code\u003e names can coexist, \u003ccode\u003eRuleSet\u003c/code\u003e resources with mismatching \u003ccode\u003eauthClassName\u003c/code\u003e will be ignored by a particular deployment. In addition, Kubernetes API server validation requests for mismatching rule sets result in a successful response. This behavior is required as otherwise, as soon as the API server receives even a single failed validation response, the affected \u003ccode\u003eRuleSet\u003c/code\u003e resource will be discarded and not made available for loading to any of the available heimdall deployments.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThat also means, if there is no heimdall deployment feeling responsible for the given \u003ccode\u003eRuleSet\u003c/code\u003e resource (due to \u003ccode\u003eauthClassName\u003c/code\u003e - \u003ccode\u003eauth_class\u003c/code\u003e mismatch), the affected \u003ccode\u003eRuleSet\u003c/code\u003e resource will be silently ignored.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_examples_4\"\u003eExamples\u003c/h3\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 8. Minimal possible configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, the provider is just enabled. Since no \u003ccode\u003eauth_class\u003c/code\u003e is configured, it will load all \u003ccode\u003eRuleSet\u003c/code\u003e resources deployed to the Kubernetes environment.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ekubernetes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 9. Configuration with \u003ccode\u003eauth_class\u003c/code\u003e set\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, the provider is configured to consider only those \u003ccode\u003eRuleSet\u003c/code\u003e resources, which \u003ccode\u003eauthClassName\u003c/code\u003e is set to \u003ccode\u003efoo\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ekubernetes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_class\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 10. Configuration with \u003ccode\u003eauth_class\u003c/code\u003e set and enabled validating admission controller\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with the previous example, the provider is configured to consider only those \u003ccode\u003eRuleSet\u003c/code\u003e resources, which \u003ccode\u003eauthClassName\u003c/code\u003e is set to \u003ccode\u003efoo\u003c/code\u003e. The admission controller is enabled as well and will validate \u003ccode\u003eRuleSet\u003c/code\u003e resources before these are made available for loading.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ekubernetes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_class\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# below is the minimal required configuration\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/file.pem\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis provider requires a RuleSet CRD being deployed, otherwise heimdall will not be able to monitor corresponding resources and emit error messages to the log.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you have used the \u003ca href=\"/docs/getting_started/installation/#_helm_chart\"\u003eHelm Chart\u003c/a\u003e to install heimdall, this CRD is already installed. You can however install it also like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ekubectl apply \u003cspan class=\"nt\"\u003e-f\u003c/span\u003e https://raw.githubusercontent.com/dadrus/heimdall/main/charts/heimdall/crds/ruleset.yaml\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Rules"],"tags":null,"title":"Rule Providers","url":"/docs/rules/providers/"},{"categories":null,"content":" Assertions This type enables configuration of required token and claim assertions. Depending on the object type (JWT or introspection response), the assertions apply to different parts of such objects.\nscopes: Scopes Matcher (optional)\nRequired scopes given to the client.\naudience: string array (optional)\nValues to be matched in the aud claim. This assertion evaluates to true if at least one entry in the given audience array is present in the aud claim. Both cases, either as whitespace separated string, or a JSON array are considered.\nissuers: string array (optional)\nIssuers to trust.\nallowed_algorithms: string array (optional)\nAlgorithms, which are trusted (according to RFC 7518). Defaults to the following list: ES256, ES384, ES512, PS256, PS384, PS512.\nvalidity_leeway Duration (optional)\nThe time leeway to consider while verifying the iat, exp and the nbf. Defaults to 10 seconds.\nExample 1. Assertions configuration issuers: - foo - bar audience: - zap scopes: - baz allowed_algorithms: - ES512 validity_leeway: 5s Here we say, the token must have been issued either by the issuer foo, or the issuer bar, the aud claim must contain zap, the scope claim (either scp or scope) must be present and contain the scope baz, if the token or the introspection response is signed, it must have been signed by using the ES512 algorithm (ECDSA using P-521 and SHA-512) and if the information about token validity is present, we respect a deviation of 5 seconds.\nAuthentication Data Source An authentication data source is actually a list of possible strategies for subject authentication data retrieval. The entries following the first one are fallbacks and are only executed if the previous strategy could not retrieve the required authentication data from the request.\nThis fallback mechanism can become handy, if different clients of your application send the authentication data using different methods. RFC 6750 describes for example how to use bearer tokens in HTTP requests to access OAuth 2.0 protected resources. This RFC says, a token can either be sent in the Authorization header, or in a query parameter, or even as part of the HTTP body. So you can define the following list to let Heimdall try to extract the access token from all three places:\n- header: Authorization scheme: Bearer - query_parameter: access_token - body_parameter: access_token The available strategies are described in the following sections.\nCookie Strategy This strategy can retrieve authentication data from a specific HTTP cookie. Following properties are supported:\ncookie: string (mandatory)\nThe name of the cookie to use.\nExample 2. Cookie Strategy usage Imagine you want Heimdall to verify an authentication session, which is represented by a specific cookie before the request hits your upstream service. If the client of your upstream application, which is case of a cookie would usually be a browser sends a cookie named \u0026#34;session\u0026#34;, you can inform Heimdall to extract and use it by configuring this strategy as follows:\n- cookie: my_session_cookie Header Strategy This strategy can retrieve authentication data from a specific HTTP header. Following properties are supported:\nheader: string (mandatory)\nThe name of the header to use.\nscheme: string (optional)\nScheme, which should be present in the header value. If specified, but not present in the header value, the authentication data cannot be retrieved, effectively making the affected authenticator feel not responsible for the request.\nExample 3. Header Strategy usage Imagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the HTTP Authorization header, you can inform Heimdall to extract it from there by configuring this strategy as follows:\n- header: Authorization scheme: Bearer Query Parameter Strategy query_parameter: string (mandatory)\nThe name of the query parameter to use.\nExample 4. Query Parameter Strategy usage Imagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the query parameter named \u0026#34;access_token\u0026#34;, you can inform Heimdall to extract it from there by configuring this strategy as follows:\n- query_parameter: access_token Body Parameter Strategy The usage of this strategy is only possible when the request payload is either JSON or application/x-www-form-urlencoded encoded. The Content-Type of the request must also either be set to application/x-www-form-urlencoded or to a MIME type, which contains json.\nbody_parameter: string (mandatory)\nThe name of the body parameter to use.\nExample 5. Body Parameter Strategy usage Imagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the body parameter named \u0026#34;access_token\u0026#34;, you can inform Heimdall to extract it from there by configuring this strategy as follows:\n- body_parameter: access_token Authentication Data Forward Strategy Authentication data strategy defines the way how heimdall should forward the authentication data extracted from the request to the used identity management system.\nAn Authentication Data Forward Strategy configuration entry must contain the following two properties:\ntype - The type of the strategy. Available types are described in the following sections.\nconfig - The strategy specific configuration.\nBody Forward Strategy This strategy can be used to embed the extracted authentication data into a body parameter of the request to the identity management system.\ntype must be set to body. config supports the following properties:\nname: string (mandatory)\nThe name of the property for the authentication data.\nExample 6. Body strategy configuration The following snippet shows how to configure this strategy to send e.g. a token in a property named \u0026#34;idToken\u0026#34;.\ntype: body config: name: idToken Depending on the configured \u0026#34;Content-Type\u0026#34; header for the request (see Endpoint headers) the result might look like\nidToken=\u0026lt;whatever the token value is\u0026gt; if the \u0026#34;Content-Type\u0026#34; header was set to application/x-www-form-urlencoded, or\n{ \u0026#34;idToken\u0026#34;: \u0026#34;\u0026lt;whatever the token value is\u0026gt;\u0026#34; } otherwise\nCookie Forward Strategy This strategy can be used to embed the extracted authentication data into a cookie of the request to the identity management system.\ntype must be set to cookie. config supports the following properties:\nname: string (mandatory)\nThe name of the cookie for the authentication data.\nExample 7. Cookie strategy configuration The following snippet shows how to configure this strategy to send e.g. a token in a cookie named \u0026#34;it_token\u0026#34;.\ntype: cookie config: name: it_token Header Forward Strategy This strategy can be used to embed the extracted authentication data into a header of the request to the identity management system.\ntype must be set to header. config supports the following properties:\nname: string (mandatory)\nThe name of the header for the authentication data.\nscheme: string (optional)\nThe scheme for the header added in front of the authentication data value.\nExample 8. Header strategy configuration The following snippet shows how to configure this strategy to send e.g. a token in a header named \u0026#34;X-ID-Token\u0026#34; with scheme \u0026#34;Bearer\u0026#34;.\ntype: header config: name: X-ID-Token scheme: Bearer Query Forward Strategy This strategy can be used to embed the extracted authentication data into a query parameter of the request to the identity management system.\nUsing this strategy is discouraged, as it will expose the authentication data to access logs, metrics and tracing. type must be set to query. config supports the following properties:\nname: string (mandatory)\nThe name of the query parameter for the authentication data.\nExample 9. Query strategy configuration The following snippet shows how to configure this strategy to send e.g. a token in a query named \u0026#34;token\u0026#34;.\ntype: query config: name: token Authentication Strategy Authentication strategy is kind of abstract type, so you have to define which specific type to use. Each type has its own configuration options.\nAn AuthStrategy configuration entry must contain the following two properties:\ntype - The type of the strategy. Available types are described in the following sections.\nconfig - The strategy specific configuration.\nAvailable strategies are described in the following sections.\nAPI Key Strategy This strategy can be used if your endpoint expects a specific api key be sent in a header, a cookie or query.\ntype must be set to api_key. config supports the following properties:\nin: string (mandatory)\nWhere to put the api key. Can be either header, cookie, or query.\nUsing query strategy will expose the api key to access logs and tracing. name: string (mandatory)\nThe name of either the header or the cookie.\nvalue: string (mandatory)\nThe value of the api key.\nExample 10. API Key Strategy configuration The following snippet shows how to configure this strategy to send an api key in the X-My-API-Key HTTP header.\ntype: api_key config: in: header name: X-My-API-Key value: super-duper-secret-key Basic Auth Strategy This strategy can be used if your endpoint is protected by HTTP basic authentication and expects the HTTP Authorization header with required values.\ntype must be set to basic_auth. config supports the following properties:\nuser: string (mandatory)\nThe user-id.\npassword: string (mandatory)\nThe password.\nExample 11. Basic Auth Strategy configuration The following snippet shows how to configure this strategy with user set to \u0026#34;Alladin\u0026#34; and password set to \u0026#34;open sesame\u0026#34;\ntype: basic_auth config: user: Alladin password: open sesame HTTP Message Signatures This strategy implements HTTP message signatures according to RFC 9421 to sign outbound requests.\ntype must be set to http_message_signatures. config supports the following properties:\nttl: Duration (optional)\nThe TTL of the resulting signature. Defaults to 1m. Responsible for setting created and expires parameters in the resulting signature.\nlabel: string (optional)\nThe label to use. Defaults to sig.\ncomponents: string array (mandatory)\nThe components to be covered by the signature. While the RFC allows for signatures that do not cover any components, this is considered a security risk. When using the \u0026#34;content-digest\u0026#34; component, Heimdall will compute hash values of the request body using sha-256 and sha-512 algorithms. It will then add a Content-Digest header with these hash values to the request, and this header will be included in the signature calculation.\nsigner: Signer (mandatory)\nThe configuration of the key material used for signature creation purposes, as well as the name used for the tag parameter in the resulting signature.\nExample 12. Strategy configuration type: http_message_signatures config: ttl: 2m label: foo components: [\u0026#34;@method\u0026#34;, \u0026#34;content-digest\u0026#34;, \u0026#34;@authority\u0026#34;, \u0026#34;x-my-fancy-header\u0026#34;] signer: name: bar key-store: path: /path/to/key.pem OAuth2 Client Credentials Grant Flow Strategy This strategy implements the OAuth2 Client Credentials Grant Flow to obtain an access token expected by the endpoint. Heimdall caches the received access token.\ntype must be set to oauth2_client_credentials. config supports the following properties:\ntoken_url: string (mandatory)\nThe token endpoint of the authorization server.\nUsage of TLS is enforced as long as heimdall is not started with --insecure-skip-egress-tls-enforcement flag, which allows insecure communication to any of the configured services. client_id: string (mandatory)\nThe client identifier for heimdall.\nclient_secret: string (mandatory)\nThe client secret for heimdall.\nauth_method: string (optional)\nThe authentication method to be used according to RFC 6749, Client Password. Can be one of\nbasic_auth (default if auth_method is not set): With that authentication method, the \u0026#34;application/x-www-form-urlencoded\u0026#34; encoded values of client_id and client_secret are sent to the authorization server via the Authorization header using the Basic scheme.\nrequest_body: With that authentication method the client_id and client_secret are sent in the request body together with the other parameters (e.g. scopes) defined by the flow.\nUsage of request_body authentication method is not recommended and should be avoided. scopes: string array (optional)\nThe scopes required for the access token.\ncache_ttl: Duration (optional)\nHow long to cache the token received from the token endpoint. Defaults to the token expiration information from the token endpoint (the value of the expires_in field) if present. If the token expiration inforation is not present and cache_ttl is not configured, the received token is not cached. If the token expiration information is present in the response and cache_ttl is configured the shorter value is taken. If caching is enabled, the token is cached until 5 seconds before its expiration. To disable caching, set it to 0s. The cache key calculation is based on the values of token_url, client_id, client_secret and the scopes properties.\nheader: object (optional, overridable)\nDefines the name and scheme to be used for the header. Defaults to Authorization with scheme Bearer. If defined, the name property must be set. If scheme is not defined, no scheme will be prepended to the resulting JWT.\nExample 13. Strategy configuration type: oauth2_client_credentials config: header: name: X-My-Token token_url: https://my-auth.provider/token client_id: foo client_secret: bar auth_method: basic_auth ttl: 10m scopes: - baz - zap Authorization Expression Authorization expressions define, as the name implies expressions for authorization purposes and have the following properties:\nexpression string (mandatory)\nThe expression to execute.\nmessage string (optional)\nThe message to include into the error if the expression fails.\nExample 14. Example expression using CEL The expression below determine whether attributes property of a subject object (also shown below) has at least one key that starts with the group prefix, and ensure that all group-like keys have list values containing only strings that end with @acme.co.\nsubject id: \u0026#34;foobar\u0026#34; attributes: group1: [\u0026#34;admin@acme.co\u0026#34;, \u0026#34;analyst@acme.co\u0026#34;] labels: [\u0026#34;metadata\u0026#34;, \u0026#34;prod\u0026#34;, \u0026#34;pii\u0026#34;] groupN: [\u0026#34;forever@acme.co\u0026#34;] expression: | subject.attributes.exists(c, c.startsWith(\u0026#39;group\u0026#39;)) \u0026amp;\u0026amp; subject.attributes .filter(c, c.startsWith(\u0026#39;group\u0026#39;)) .all(c, subject.attributes[c] .all(g, g.endsWith(\u0026#39;@acme.co\u0026#39;))) message: No groups ending with @acme.co present ByteSize ByteSize is actually a string type, which adheres to the following pattern: ^[0-9]+(B|KB|MB)$\nSo with 10B you can define the byte size of 10 bytes and with 2MB you can say 2 megabytes.\nCORS CORS (Cross-Origin Resource Sharing) headers can be added and configured by making use of this type. This functionality allows for advanced security features to quickly be set. If CORS headers are set, then heimdall does not pass preflight requests to its decision pipeline, instead the response will be generated and sent back to the client directly. Following properties are supported:\nallowed_origins: string array (optional)\nList of origins that may access the resource. Defaults to all, if not set, but any of the other CORS options are configured.\nallowed_methods: string array (optional)\nList of methods allowed when accessing the resource. This is used in response to a preflight request. Defaults to GET, POST, HEAD, PUT, DELETE and PATCH if not set, but any of the other CORS options are configured.\nallowed_headers: string array (optional)\nList of request headers that can be used when making the actual request.\nexposed_headers: string array (optional)\n\u0026#34;Allow-List\u0026#34; of headers that clients are allowed to access.\nallow_credentials: boolean (optional)\nIndicates whether the response to the request can be exposed when the credentials flag is true. When used as part of a response to a preflight request, this indicates whether the actual request can be made using credentials. Defaults to false if not set, but any of the other CORS options are configured.\nmax_age: Duration (optional)\nIndicates how long the results of a preflight request can be cached. Defaults to 0 seconds if not set, but any of the other CORS options are configured.\nExample 15. Possible configuration allowed_origins: - example.org allowed_methods: - HEAD - PATCH allow_credentials: true max_age: 10s Duration Duration is actually a string type, which adheres to the following pattern: ^[0-9]+(ns|us|ms|s|m|h)$\nSo with 10s you can define the duration of 10 seconds and with 2h you can say 2 hours.\nEndpoint The Endpoint type defines the properties required for communication with an endpoint.\nIf only the URL needs to be set, you can specify it as a string. If additional properties are required, the following options are available:\nurl string (mandatory)\nThe URL of the endpoint. Depending on the mechanism, the URL can be templated.\nIf templating is used, the user info, scheme, and host parts of the URL cannot be templated. Attempts to do so will result in runtime errors.\nTLS is enforced unless heimdall is started with the --insecure-skip-egress-tls-enforcement flag, which allows insecure communication with any configured service.\nmethod string (optional)\nThe HTTP method to use while communicating with the endpoint. If not set POST is used.\nretry Retry (optional)\nWhat to do if the communication fails. If not configured, no retry attempts are done.\nauth Authentication Strategy (optional)\nAuthentication strategy to apply, if the endpoint requires authentication.\nheaders map of strings (optional)\nHTTP headers to be sent to the endpoint.\nThese headers are not analyzed by heimdall and are just forwarded to the endpoint. E.g. if you configure the Content-Encoding to something like gzip, the service behind the used endpoint might fail to answer, as it would expect the body to be compressed. http_cache object (optional)\nControls whether HTTP caching according to RFC 7234 should be used. To support this, that object defines the following properties:\nenabled boolean (optional)\nDefaults to false if not otherwise stated in the description of the configuration type, making use of the endpoint property. If set to true heimdall will strictly follow the requirements from RFC 7234 and cache the responses if possible and reuse these if still valid.\ncache_ttl Duration (optional)\nSpecifies how long heimdall should cache the response if the endpoint referenced by the URL does not provide any explicit expiration time (no heuristic freshness lifetime is calculated). Without configuring this property, heimdall treats such responses as not cacheable. Defaults to 0s if not otherwise stated in the description of the configuration type making use of the endpoint property.\nExample 16. Endpoint configuration as string https://foo.bar Example 17. Structured Endpoint configuration url: https://foo.bar method: GET retry: give_up_after: 5s max_delay: 1s auth: type: api_key config: name: foo value: bar in: cookie headers: X-My-First-Header: foobar X-My-Second-Header: barfoo http_cache: enabled: true Error/State Type Heimdall defines a couple of error/state types, which it uses to signal errors. Those, which are marked with (*) are available in CEL expressions. All can be used to define overrides for the HTTP response codes.\nFollowing types are available:\naccepted - this is the only state type in this list and is used to signal, the matched decision pipeline has been executed successfully, so the request can be forwarded to the upstream service. The response of that type results by default in a 200 OK response.\nauthentication_error (*) - used if an authenticator failed to verify authentication data available in the request. E.g. an authenticator was configured to verify a JWT and the signature of it was invalid. If none of the authenticators used in a pipeline were able to authenticate the user, and the default error handler was used to handle such error, it will by default result in a 401 Unauthorized response.\nauthorization_error (*) - used if an authorizer failed to authorize the subject. E.g. an authorizer is configured to use an expression on the given subject and request context, but that expression returned with an error. Error of this type results by default in 403 Forbidden response if the default error handler was used to handle such error.\ncommunication_error (*) - this error is used to signal a communication error while communicating to a remote system during the execution of the pipeline of the matched rule. Timeouts of DNSs errors result in such an error. Error of this type results by default in 502 Bad Gateway HTTP code if handled by the default error handler.\ninternal_error - used if heimdall run into an internal error condition while processing the request. E.g. something went wrong while unmarshalling a JSON object, or if there was a configuration error, which couldn’t be raised while loading a rule, etc. Results by default in 500 Internal Server Error response to the caller.\nno_rule_error - this error is used to signal, there is no matching rule to handle the given request. Error of this type results by default in 404 Not Found HTTP code.\nprecondition_error (*) - used if the request does not contain required/expected data. E.g. if an authenticator could not find a cookie configured. Error of this type results by default in 400 Bad Request HTTP code if handled by the default error handler.\nKey Store This type configures a key store holding keys and corresponding certificate chains. PKCS#1, as well as PKCS#8 encodings are supported for private keys.\nWhile loading a key store following verifications are done:\nUniqueness of key ids and rejection of key stores which violate this condition (see also Key-Id Lookup)\nCorrelation of keys and certificates to build a valid certificate chain for every given key if certificates are present. If the correlation fails, an error is raised and heimdall will refuse to start.\nCertificate chain validation. If the chain is invalid, an error is raised and heimdall will refuse to start.\nFollowing configuration properties are available:\npath: string (mandatory)\nThe path to the PEM file with the cryptographic material. Watching for secrets rotation is supported.\npassword: string (optional)\nIf the key material is protected with a password, this property can be set to decipher it. Password protection is only supported for PKCS#8 encoded keys\nIf the key store contains multiple keys and these keys are password protected, same password must be used for all of these. Example 18. Example configuration path: /path/to/keystore.pem password: VeryInsecure! Respond This type enables instructing heimdall to preserve error information and provide it in the response body to the caller, as well as to use HTTP status codes deviating from those heimdall would usually use. The configuration, which can be done using this type affects only the behavior of the default error handler.\nFollowing properties are supported:\nverbose: boolean (optional)\nBy making use of this property you can instruct heimdall to preserve error information and provide it in the response body to the caller. Defaults to false.\nHeimdall supports MIME type negotiation. So, if the client sets the HTTP Accept header to e.g. application/json, and Heimdall run into an unhandled internal error condition, in addition to responding with 500 Internal Server Error, it will render an error message, like shown below, if verbose has been set to true.\n{ \u0026#34;code\u0026#34;: \u0026#34;internal error\u0026#34;, \u0026#34;message\u0026#34;: \u0026#34;whatever led to the error\u0026#34; } The message will however contain just high-level information, like \u0026#34;failed to parse something\u0026#34;, but will not contain any stack traces.\nwith: ResponseOverride set (optional)\nThis property enables mapping between response/error types used by heimdall and the corresponding HTTP status codes. Each entry must be from the list of the supported Error/State Types and contain exactly one property named code, which then defines the desired mapping.\nExample 19. Making error responses verbose and changing the HTTP codes for some errors verbose: true with: authentication_error: code: 404 authorization_error: code: 404 Retry Implements an exponential backoff strategy for endpoint communication. It increases the backoff exponentially by multiplying the max_delay with 2^(attempt count)\ngive_up_after: Duration (optional)\nSets an upper bound on the maximum time to wait between two requests. Default to 0, which means no upper bound.\nmax_delay: Duration (mandatory)\nThe initial backoff.\nExample 20. Retry configuration In this example the backoff will be 1, 2, 4, 8, 16, 32, 60, …​\ngive_up_after: 60s max_delay: 1s Scopes Matcher Scopes matcher is a configuration type allowing configuration of different strategies to match required scopes. In its simplest shape it can be just an array of strings (implemented by the Exact) scope matcher. To cover many use cases, different strategies are available and described in the following sections.\nRegardless of the strategy, each matcher can explicitly be configured and supports the following configuration properties:\nmatching_strategy - the type of the mathing strategy.\nvalues - the list of scope patterns\nExact This the simplest matcher and is automatically selected, if just an array of strings is configured as shown in the following snippet:\n- foo - bar However, as written in the Scopes Matcher section, it can also explicitly be selected by setting matching_strategy to exact and defining the required scopes in the values property.\nExample 21. Essentially same configurations matching_strategy: exact values: - foo - bar - foo - bar Hierarchic This matcher enables matching hierarchical scopes, which use . as separator. Imagine your system is organized that way, that it defines namespaces for different services like this:\nmy-service being the top namespace\nmy-service.booking - being the namespace of the booking service\nmy-service.orders - being the namespace of the orders service\nmy-service.orders.partners - being the namespace of the order service for partners and\nmy-service.orders.customers - being the namespace of the order service for customers\nBasically you’ve established an identity for each of your services (this is comparable to how SPIFFE IDs are organized and also used for).\nNow, imagine you use these namespaces as scope values to limit the usage of the issued tokens. In such situations the hierarchic scope matcher can become handy if you would like to assert any scope of the token must be in e.g. the my-service or the my-service.orders namespace.\nThis matcher can only be used by explicitly setting the matching_strategy to hierarchic and defining the required patterns in the values property.\nExample 22. Matching of hierarchic scopes matching_strategy: hierarchic values: - my-service This configuration will ensure all scopes withing the scope or scp claim are within the my-service namespace. So scope claim like\n{ \u0026#34;scope\u0026#34;: [\u0026#34;my-service.orders\u0026#34;, \u0026#34;my-service.orders.customers\u0026#34;] } would match, but\n{ \u0026#34;scope\u0026#34;: [\u0026#34;not-my-service\u0026#34;, \u0026#34;my-service.orders.customers\u0026#34;] } would not match.\nWildcard This matcher enables matching scopes using wildcards. It goes beyond the Hierarchic scope matcher by enabling usage of wildcards.\nThis matcher can only be used by explicitly setting the matching_strategy to wildcard and defining the required patterns in the values property.\nSession Lifespan This configuration type enables the configuration of session lifespans, used for session validation for those authenticators, which act on non-standard protocols. Following properties are available.\nactive: string (optional)\nA GJSON Path pointing to the field describing the \u0026#34;active\u0026#34; status of the session in the corresponding JSON object. The actual value in that field should be convertable to a bool type. If not provided, or not found in the session object, the session is considered to be \u0026#34;active\u0026#34;. \u0026#34;active\u0026#34; means it can be used and represent a valid session between the authentication system and the subject, the session has been issued to.\nissued_at: string (optional)\nA GJSON Path pointing to the field in the corresponding JSON object, describing the time, when the session object has been issued. If not provided or not found, the issuance time is not considered during session validation.\nnot_before: string (optional)\nA GJSON Path pointing to the field in the corresponding JSON object describing the time, until which the session object is not allowed to be used. If not provided or not found, the corresponding time is not considered during session validation.\nnot_after: string (optional)\nA GJSON Path pointing to the field in the corresponding JSON object describing the time, after which the session object is not allowed to be used. If not provided or not found, the corresponding time is not considered during session validation.\ntime_format: string (optional)\nSince different authentication system use different representations for time strings, this property allows the definition of the time format/layout used by the authentication system. Defaults to Unix Epoch time stamp.\nYou can use the following Go Playground link to test your time format settings. validity_leeway: Duration (optional)\nEnables definition of an allowed time drift between the authentication system and heimdall for the validation of the session validity. Defaults to 0.\nExample 23. Making use of session information received from Ory’s Kratos A typical response from Kratos\u0026#39; whoami endpoint looks like follows (stripped to the most interesting parts):\n{ \u0026#34;id\u0026#34;: \u0026#34;1338410d-c473-4503-a96a-53efa06e2531\u0026#34;, \u0026#34;active\u0026#34;: true, \u0026#34;expires_at\u0026#34;: \u0026#34;2021-10-15T15:58:57.683338Z\u0026#34;, \u0026#34;authenticated_at\u0026#34;: \u0026#34;2021-10-14T15:58:57.683338Z\u0026#34;, \u0026#34;issued_at\u0026#34;: \u0026#34;2021-10-14T15:58:57.683338Z\u0026#34;, \u0026#34;identity\u0026#34;: { \u0026#34;id\u0026#34;: \u0026#34;9496bbd5-f426-473f-b087-c7df853f274a\u0026#34;, ... } } To enable usage of these properties in Heimdall, you can configure the Session Lifespan as follows:\nactive: active issued_at: issued_at not_before: authenticated_at not_after: expires_at time_format: \u0026#34;2006-01-02T15:04:05.999999Z07\u0026#34; validity_leeway: 10s Example 24. Making use of session information received from a compliant OAuth2 authorization service A typical response from a token introspection endpoint looks like follows:\n{ \u0026#34;active\u0026#34;: true, \u0026#34;client_id\u0026#34;: \u0026#34;l238j323ds-23ij4\u0026#34;, \u0026#34;username\u0026#34;: \u0026#34;jdoe\u0026#34;, \u0026#34;scope\u0026#34;: \u0026#34;read write dolphin\u0026#34;, \u0026#34;sub\u0026#34;: \u0026#34;Z5O3upPC88QrAjx00dis\u0026#34;, \u0026#34;aud\u0026#34;: \u0026#34;https://protected.example.net/resource\u0026#34;, \u0026#34;iss\u0026#34;: \u0026#34;https://server.example.com/\u0026#34;, \u0026#34;exp\u0026#34;: 1419356238, \u0026#34;iat\u0026#34;: 1419350238, \u0026#34;extension_field\u0026#34;: \u0026#34;twenty-seven\u0026#34; } To enable usage of these properties in Heimdall, you can configure the Session Lifespan as follows:\nactive: active issued_at: iat not_after: exp validity_leeway: 10s As you see, there is no need to define the time format as the times values appearing in the responses from an introspection endpoint are Unix Epoch time stamps.\nSigner When heimdall is used to issue signed objects, like JWTs, to enable upstream services to rely on authentic information, it acts as an issuer of such objects and requires corresponding configuration.\nFollowing properties are supported:\nname: string (optional)\nThe name used to specify the issuer. E.g. if a JWT is generated, this value is used to set the iss claim. If not set, the value heimdall is used.\nkey_store: Key Store (mandatory)\nThe key store containing the cryptographic material. At least one private key must be present.\nkey_id: string (optional)\nIf the key_store contains multiple keys, this property can be used to specify the key to use (see also Key-Id Lookup). If not specified, the first key is used. If specified, but there is no key for the given key id present, an error is raised and heimdall will refuse to start.\nExample 25. Possible configuration Imagine you have a PEM file located in /opt/heimdall/keystore.pem with the following contents:\n-----BEGIN EC PRIVATE KEY----- X-Key-ID: foo MIGkAgEBBDBRLr783dIM5NHJnDDMRVBiFSF56xqHle5lZk1ZCyyow9wKZGuF4EWK jRBISBkE3NSgBwYFK4EEACKhZANiAAQ+oGUOJpVjntIWuanYxpXe6oN5tKhzLhBX GP1SOXiLhnPNnN2uZu9KwOoBzoZhr/Fxw+sziXmzHJwjluz78VOlFKyopxTfmxRZ 0qq3f/KHWdDtVvmTfT0O/ux9mg6mCJw= -----END EC PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIByjCCAVGgAwIBAgIBATAKBggqhkjOPQQDAzAuMQswCQYDVQQGEwJFVTENMAsG A1UEChMEVGVzdDEQMA4GA1UEAxMHVGVzdCBDQTAeFw0yMjA4MTUwOTE3MTFaFw0y MjA4MTUxMDE3MTFaMDAxCzAJBgNVBAYTAkVVMQ0wCwYDVQQKEwRUZXN0MRIwEAYD VQQDEwlUZXN0IEVFIDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ+oGUOJpVjntIW uanYxpXe6oN5tKhzLhBXGP1SOXiLhnPNnN2uZu9KwOoBzoZhr/Fxw+sziXmzHJwj luz78VOlFKyopxTfmxRZ0qq3f/KHWdDtVvmTfT0O/ux9mg6mCJyjQTA/MA4GA1Ud DwEB/wQEAwIHgDAMBgNVHQ4EBQQDYmFyMB8GA1UdIwQYMBaAFLO77bgPgZMKz11D BVDUXvtNGeBnMAoGCCqGSM49BAMDA2cAMGQCMFRlx9Bq0MuSh5pDhDTqRq/MnxxD W7qZg15AXoNnLrR60vV9gHjzkp1UkcU9viRIuAIwU0BjwDncp9z1seqKh+/eJV3f xstQe2rzUEptWLIiPFoOBWZuw9wJ/Hunjik3a9T/ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIByjCCAVCgAwIBAgIBATAKBggqhkjOPQQDAzAuMQswCQYDVQQGEwJFVTENMAsG A1UEChMEVGVzdDEQMA4GA1UEAxMHVGVzdCBDQTAeFw0yMjA4MTUwOTE3MTFaFw0y MjA4MTYwOTE3MTFaMC4xCzAJBgNVBAYTAkVVMQ0wCwYDVQQKEwRUZXN0MRAwDgYD VQQDEwdUZXN0IENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEf96tstMNdNoNfYjl bGY6BvBFTsl9E3hpPnta7SJn6BqIYz6KEohDJ+8DXwUMVb5Ytr/QkEikg966HCY3 A9TFBUdAs01TV8f2KoAPRQVrh+ccSLLJyACENfZ5VbGSQ0wso0IwQDAOBgNVHQ8B Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUs7vtuA+BkwrPXUMF UNRe+00Z4GcwCgYIKoZIzj0EAwMDaAAwZQIxAMPgE/Z+1Dcj+lH7jioE16Hig0HQ FC4qBx1UU05H05Gs23ECB1hzD2qXikVpaNyuDgIwbogEu42wIwpDa5xdJIZcIhmz DIuPvEscUDjU3C+1GPxmACcRMPv9QVUEcBAvZkfn -----END CERTIFICATE----- Then you can configure heimdall to use it like follows:\nsigner: name: foobar key_store: path: /opt/heimdall/keystore.pem key_id: foo Subject This configuration type enables extraction of subject information from responses received by Heimdall from authentication services. Following properties are available.\nid: string (mandatory)\nA GJSON Path pointing to the id of the subject in the JSON object.\nattributes: string (optional)\nA GJSON Path pointing to the attributes of the subject in the JSON object. Defaults to @this.\nExample 26. Extracting subject id from an OAuth2 Introspection endpoint response. This example shows how to extract the subject id from an OAuth2 Introspection endpoint response and set the subject attributes to the entire response\nid: sub attributes: @this Setting attributes was actually not required, as @this would be set by default anyway.\nExample 27. Extracting subject id from an Ory Kratos \u0026#34;whoami\u0026#34; endpoint response This example shows how to extract the subject id from an Ory Kratos \u0026#34;whoami\u0026#34; endpoint response and set the subject attributes to the entire response. attributes is not configured, so default is used.\nid: identity.id TLS Following are the supported TLS configuration properties:\nkey_store: Key Store (mandatory)\nThe key store containing the cryptographic material. At least one private key and the corresponding certificate must be present.\nkey_id: string (optional)\nIf the key_store contains multiple keys, this property can be used to specify the key to use (see also Key-Id Lookup). If not specified, the first key is used. If specified, but there is no key for the given key id present, an error is raised and heimdall will refuse to start.\nmin_version: string (optional)\nThe minimal TLS version to support. Can be either TLS1.2 or TLS1.3. Defaults to TLS1.3.\ncipher_suites: string array (optional)\nCan be configured if min_version is set to TLS1.2. If min_version is set to TLS1.3 the configured values are ignored. Only the following PFS cipher suites are supported:\nTLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\nTLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\nTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\nTLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\nTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\nTLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\nTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\nTLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\nDefaults to the last six cipher suites if min_version is set to TLS1.2 and cipher_suites is not configured.\nExample 28. Example configuration key_store: path: /path/to/keystore.pem password: VeryInsecure! key_id: foobar min_version: TLS1.2 cipher_suites: - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 Key-Id Lookup When heimdall loads a key store, following algorithm is used to get the key id for the key:\nif the PEM entry with the private key has X-Key-ID header specified, this value is used as key id\nOtherwise, if an X.509 certificate is present for the private key, and it has the Subject Key Identifier extension set, the hex representation of it is used as key id.\nOtherwise, heimdall calculates the value for the Subject Key Identifier according to RFC 3280, Section 4.2.1.2 and uses hex representation of it as key id.\n","description":"","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_assertions\"\u003eAssertions\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis type enables configuration of required token and claim assertions. Depending on the object type (JWT or introspection response), the assertions apply to different parts of such objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escopes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_scopes_matcher\"\u003eScopes Matcher\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRequired scopes given to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eaudience\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eValues to be matched in the \u003ccode\u003eaud\u003c/code\u003e claim. This assertion evaluates to \u003ccode\u003etrue\u003c/code\u003e if at least one entry in the given \u003ccode\u003eaudience\u003c/code\u003e array is present in the \u003ccode\u003eaud\u003c/code\u003e claim. Both cases, either as whitespace separated string, or a JSON array are considered.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eissuers\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIssuers to trust.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallowed_algorithms\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAlgorithms, which are trusted (according to \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7518\"\u003eRFC 7518\u003c/a\u003e). Defaults to the following list: ES256, ES384, ES512, PS256, PS384, PS512.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalidity_leeway\u003c/code\u003e\u003c/strong\u003e \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe time leeway to consider while verifying the \u003ccode\u003eiat\u003c/code\u003e, \u003ccode\u003eexp\u003c/code\u003e and the \u003ccode\u003enbf\u003c/code\u003e. Defaults to 10 seconds.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Assertions configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n\u003cspan class=\"na\"\u003eaudience\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ezap\u003c/span\u003e\n\u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebaz\u003c/span\u003e\n\u003cspan class=\"na\"\u003eallowed_algorithms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eES512\u003c/span\u003e\n\u003cspan class=\"na\"\u003evalidity_leeway\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere we say, the token must have been issued either by the issuer \u003ccode\u003efoo\u003c/code\u003e, or the issuer \u003ccode\u003ebar\u003c/code\u003e, the \u003ccode\u003eaud\u003c/code\u003e claim must contain \u003ccode\u003ezap\u003c/code\u003e, the scope claim (either \u003ccode\u003escp\u003c/code\u003e or \u003ccode\u003escope\u003c/code\u003e) must be present and contain the scope \u003ccode\u003ebaz\u003c/code\u003e, if the token or the introspection response is signed, it must have been signed by using the \u003ccode\u003eES512\u003c/code\u003e algorithm (ECDSA using P-521 and SHA-512) and if the information about token validity is present, we respect a deviation of 5 seconds.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authentication_data_source\"\u003eAuthentication Data Source\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAn authentication data source is actually a list of possible strategies for subject authentication data retrieval. The entries following the first one are fallbacks and are only executed if the previous strategy could not retrieve the required authentication data from the request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis fallback mechanism can become handy, if different clients of your application send the authentication data using different methods. \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc6750\"\u003eRFC 6750\u003c/a\u003e describes for example how to use bearer tokens in HTTP requests to access OAuth 2.0 protected resources. This RFC says, a token can either be sent in the \u003ccode\u003eAuthorization\u003c/code\u003e header, or in a query parameter, or even as part of the HTTP body. So you can define the following list to let Heimdall try to extract the access token from all three places:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003equery_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ebody_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe available strategies are described in the following sections.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_cookie_strategy\"\u003eCookie Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can retrieve authentication data from a specific HTTP cookie. Following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecookie\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the cookie to use.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Cookie Strategy usage\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you want Heimdall to verify an authentication session, which is represented by a specific cookie before the request hits your upstream service. If the client of your upstream application, which is case of a cookie would usually be a browser sends a cookie named \u0026#34;session\u0026#34;, you can inform Heimdall to extract and use it by configuring this strategy as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ecookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy_session_cookie\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_header_strategy\"\u003eHeader Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can retrieve authentication data from a specific HTTP header. Following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheader\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the header to use.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escheme\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eScheme, which should be present in the header value. If specified, but not present in the header value, the authentication data cannot be retrieved, effectively making the affected authenticator feel not responsible for the request.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Header Strategy usage\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the HTTP \u003ccode\u003eAuthorization\u003c/code\u003e header, you can inform Heimdall to extract it from there by configuring this strategy as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_query_parameter_strategy\"\u003eQuery Parameter Strategy\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003equery_parameter\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the query parameter to use.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Query Parameter Strategy usage\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the query parameter named \u0026#34;access_token\u0026#34;, you can inform Heimdall to extract it from there by configuring this strategy as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003equery_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_body_parameter_strategy\"\u003eBody Parameter Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe usage of this strategy is only possible when the request payload is either JSON or \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e encoded. The \u003ccode\u003eContent-Type\u003c/code\u003e of the request must also either be set to \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e or to a MIME type, which contains \u003ccode\u003ejson\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebody_parameter\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the body parameter to use.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Body Parameter Strategy usage\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the body parameter named \u0026#34;access_token\u0026#34;, you can inform Heimdall to extract it from there by configuring this strategy as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ebody_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authentication_data_forward_strategy\"\u003eAuthentication Data Forward Strategy\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAuthentication data strategy defines the way how heimdall should forward the authentication data extracted from the request to the used identity management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAn Authentication Data Forward Strategy configuration entry must contain the following two properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e - The type of the strategy. Available types are described in the following sections.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003econfig\u003c/code\u003e - The strategy specific configuration.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_body_forward_strategy\"\u003eBody Forward Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used to embed the extracted authentication data into a body parameter of the request to the identity management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003ebody\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the property for the authentication data.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 6. Body strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy to send e.g. a token in a property named \u0026#34;idToken\u0026#34;.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebody\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eidToken\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDepending on the configured \u0026#34;Content-Type\u0026#34; header for the request (see \u003ca href=\"#_endpoint\"\u003e\u003ccode\u003eEndpoint\u003c/code\u003e\u003c/a\u003e \u003ccode\u003eheaders\u003c/code\u003e) the result might look like\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003eidToken=\u0026lt;whatever the token value is\u0026gt;\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eif the \u0026#34;Content-Type\u0026#34; header was set to \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e, or\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;idToken\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u0026lt;whatever the token value is\u0026gt;\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eotherwise\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_cookie_forward_strategy\"\u003eCookie Forward Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used to embed the extracted authentication data into a cookie of the request to the identity management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003ecookie\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the cookie for the authentication data.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 7. Cookie strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy to send e.g. a token in a cookie named \u0026#34;it_token\u0026#34;.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecookie\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eit_token\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_header_forward_strategy\"\u003eHeader Forward Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used to embed the extracted authentication data into a header of the request to the identity management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003eheader\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the header for the authentication data.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escheme\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe scheme for the header added in front of the authentication data value.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 8. Header strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy to send e.g. a token in a header named \u0026#34;X-ID-Token\u0026#34; with scheme \u0026#34;Bearer\u0026#34;.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-ID-Token\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_query_forward_strategy\"\u003eQuery Forward Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used to embed the extracted authentication data into a query parameter of the request to the identity management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsing this strategy is discouraged, as it will expose the authentication data to access logs, metrics and tracing.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003equery\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the query parameter for the authentication data.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 9. Query strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy to send e.g. a token in a query named \u0026#34;token\u0026#34;.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003equery\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etoken\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authentication_strategy\"\u003eAuthentication Strategy\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAuthentication strategy is kind of abstract type, so you have to define which specific type to use. Each type has its own configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAn AuthStrategy configuration entry must contain the following two properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e - The type of the strategy. Available types are described in the following sections.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003econfig\u003c/code\u003e - The strategy specific configuration.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAvailable strategies are described in the following sections.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_api_key_strategy\"\u003eAPI Key Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used if your endpoint expects a specific api key be sent in a header, a cookie or query.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003eapi_key\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ein\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to put the api key. Can be either \u003ccode\u003eheader\u003c/code\u003e, \u003ccode\u003ecookie\u003c/code\u003e, or \u003ccode\u003equery\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsing \u003ccode\u003equery\u003c/code\u003e strategy will expose the api key to access logs and tracing.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of either the header or the cookie.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalue\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe value of the api key.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 10. API Key Strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy to send an api key in the \u003ccode\u003eX-My-API-Key\u003c/code\u003e HTTP header.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-My-API-Key\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esuper-duper-secret-key\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_basic_auth_strategy\"\u003eBasic Auth Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used if your endpoint is protected by HTTP basic authentication and expects the HTTP \u003ccode\u003eAuthorization\u003c/code\u003e header with required values.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003ebasic_auth\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003euser\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe user-id.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epassword\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe password.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 11. Basic Auth Strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy with user set to \u0026#34;Alladin\u0026#34; and password set to \u0026#34;open sesame\u0026#34;\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAlladin\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopen sesame\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_http_message_signatures\"\u003eHTTP Message Signatures\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy implements HTTP message signatures according to \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc9421\"\u003eRFC 9421\u003c/a\u003e to sign outbound requests.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003ehttp_message_signatures\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ettl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe TTL of the resulting signature. Defaults to 1m. Responsible for setting \u003ccode\u003ecreated\u003c/code\u003e and \u003ccode\u003eexpires\u003c/code\u003e parameters in the resulting signature.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003elabel\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe label to use. Defaults to \u003ccode\u003esig\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecomponents\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe components to be covered by the signature. While the RFC allows for signatures that do not cover any components, this is considered a security risk. When using the \u003ccode\u003e\u0026#34;content-digest\u0026#34;\u003c/code\u003e component, Heimdall will compute hash values of the request body using \u003ccode\u003esha-256\u003c/code\u003e and \u003ccode\u003esha-512\u003c/code\u003e algorithms. It will then add a \u003ccode\u003eContent-Digest\u003c/code\u003e header with these hash values to the request, and this header will be included in the signature calculation.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esigner\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_signer\"\u003eSigner\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of the key material used for signature creation purposes, as well as the name used for the \u003ccode\u003etag\u003c/code\u003e parameter in the resulting signature.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 12. Strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp_message_signatures\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2m\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecomponents\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@method\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003econtent-digest\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@authority\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ex-my-fancy-header\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey-store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/key.pem\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_oauth2_client_credentials_grant_flow_strategy\"\u003eOAuth2 Client Credentials Grant Flow Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy implements the \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc6749#section-4.4\"\u003eOAuth2 Client Credentials Grant Flow\u003c/a\u003e to obtain an access token expected by the endpoint. Heimdall caches the received access token.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003eoauth2_client_credentials\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etoken_url\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe token endpoint of the authorization server.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsage of TLS is enforced as long as heimdall is not started with \u003ccode\u003e--insecure-skip-egress-tls-enforcement\u003c/code\u003e flag, which allows insecure communication to any of the configured services.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclient_id\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe client identifier for heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclient_secret\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe client secret for heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauth_method\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe authentication method to be used according to \u003ca href=\"https://www.rfc-editor.org/rfc/rfc6749#section-2.3.1\"\u003eRFC 6749, Client Password\u003c/a\u003e. Can be one of\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ebasic_auth\u003c/code\u003e (default if \u003ccode\u003eauth_method\u003c/code\u003e is not set): With that authentication method, the \u003ccode\u003e\u0026#34;application/x-www-form-urlencoded\u0026#34;\u003c/code\u003e encoded values of \u003ccode\u003eclient_id\u003c/code\u003e and \u003ccode\u003eclient_secret\u003c/code\u003e are sent to the authorization server via the \u003ccode\u003eAuthorization\u003c/code\u003e header using the \u003ccode\u003eBasic\u003c/code\u003e scheme.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003erequest_body\u003c/code\u003e: With that authentication method the \u003ccode\u003eclient_id\u003c/code\u003e and \u003ccode\u003eclient_secret\u003c/code\u003e are sent in the request body together with the other parameters (e.g. \u003ccode\u003escopes\u003c/code\u003e) defined by the flow.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsage of \u003ccode\u003erequest_body\u003c/code\u003e authentication method is not recommended and should be avoided.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escopes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe scopes required for the access token.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow long to cache the token received from the token endpoint. Defaults to the token expiration information from the token endpoint (the value of the \u003ccode\u003eexpires_in\u003c/code\u003e field) if present. If the token expiration inforation is not present and \u003ccode\u003ecache_ttl\u003c/code\u003e is not configured, the received token is not cached. If the token expiration information is present in the response and \u003ccode\u003ecache_ttl\u003c/code\u003e is configured the shorter value is taken. If caching is enabled, the token is cached until 5 seconds before its expiration. To disable caching, set it to \u003ccode\u003e0s\u003c/code\u003e. The cache key calculation is based on the values of \u003ccode\u003etoken_url\u003c/code\u003e, \u003ccode\u003eclient_id\u003c/code\u003e, \u003ccode\u003eclient_secret\u003c/code\u003e and the \u003ccode\u003escopes\u003c/code\u003e properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheader\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eobject\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines the \u003ccode\u003ename\u003c/code\u003e and \u003ccode\u003escheme\u003c/code\u003e to be used for the header. Defaults to \u003ccode\u003eAuthorization\u003c/code\u003e with scheme \u003ccode\u003eBearer\u003c/code\u003e. If defined, the \u003ccode\u003ename\u003c/code\u003e property must be set. If \u003ccode\u003escheme\u003c/code\u003e is not defined, no scheme will be prepended to the resulting JWT.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 13. Strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_client_credentials\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-My-Token\u003c/span\u003e\n \u003cspan class=\"na\"\u003etoken_url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://my-auth.provider/token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_secret\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_method\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10m\u003c/span\u003e\n \u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebaz\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ezap\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authorization_expression\"\u003eAuthorization Expression\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAuthorization expressions define, as the name implies expressions for authorization purposes and have the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/strong\u003e \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe expression to execute.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emessage\u003c/code\u003e\u003c/strong\u003e \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe message to include into the error if the expression fails.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 14. Example expression using \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe expression below determine whether \u003ccode\u003eattributes\u003c/code\u003e property of a \u003ccode\u003esubject\u003c/code\u003e object (also shown below) has at least one key that starts with the \u003ccode\u003egroup\u003c/code\u003e prefix, and ensure that all group-like keys have list values containing only strings that end with \u003ccode\u003e@acme.co\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"title\"\u003esubject\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003efoobar\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egroup1\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eadmin@acme.co\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eanalyst@acme.co\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003emetadata\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eprod\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003epii\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003egroupN\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eforever@acme.co\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e]\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003esubject.attributes.exists(c, c.startsWith(\u0026#39;group\u0026#39;)) \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003esubject.attributes\u003c/span\u003e\n \u003cspan class=\"s\"\u003e.filter(c, c.startsWith(\u0026#39;group\u0026#39;))\u003c/span\u003e\n \u003cspan class=\"s\"\u003e.all(c, subject.attributes[c]\u003c/span\u003e\n \u003cspan class=\"s\"\u003e.all(g, g.endsWith(\u0026#39;@acme.co\u0026#39;)))\u003c/span\u003e\n\u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eNo groups ending with @acme.co present\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_bytesize\"\u003eByteSize\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eByteSize is actually a string type, which adheres to the following pattern: \u003ccode\u003e^[0-9]+(B|KB|MB)$\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSo with \u003ccode\u003e10B\u003c/code\u003e you can define the byte size of 10 bytes and with \u003ccode\u003e2MB\u003c/code\u003e you can say 2 megabytes.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cors\"\u003eCORS\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS\"\u003eCORS\u003c/a\u003e (Cross-Origin Resource Sharing) headers can be added and configured by making use of this type. This functionality allows for advanced security features to quickly be set. If CORS headers are set, then heimdall does not pass preflight requests to its decision pipeline, instead the response will be generated and sent back to the client directly. Following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallowed_origins\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eList of origins that may access the resource. Defaults to all, if not set, but any of the other CORS options are configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallowed_methods\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eList of methods allowed when accessing the resource. This is used in response to a preflight request. Defaults to \u003ccode\u003eGET\u003c/code\u003e, \u003ccode\u003ePOST\u003c/code\u003e, \u003ccode\u003eHEAD\u003c/code\u003e, \u003ccode\u003ePUT\u003c/code\u003e, \u003ccode\u003eDELETE\u003c/code\u003e and \u003ccode\u003ePATCH\u003c/code\u003e if not set, but any of the other CORS options are configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallowed_headers\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eList of request headers that can be used when making the actual request.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexposed_headers\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u0026#34;Allow-List\u0026#34; of headers that clients are allowed to access.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_credentials\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIndicates whether the response to the request can be exposed when the credentials flag is true. When used as part of a response to a preflight request, this indicates whether the actual request can be made using credentials. Defaults to \u003ccode\u003efalse\u003c/code\u003e if not set, but any of the other CORS options are configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_age\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIndicates how long the results of a preflight request can be cached. Defaults to 0 seconds if not set, but any of the other CORS options are configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 15. Possible configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eallowed_origins\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eexample.org\u003c/span\u003e\n\u003cspan class=\"na\"\u003eallowed_methods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eHEAD\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePATCH\u003c/span\u003e\n\u003cspan class=\"na\"\u003eallow_credentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\u003cspan class=\"na\"\u003emax_age\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_duration\"\u003eDuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDuration is actually a string type, which adheres to the following pattern: \u003ccode\u003e^[0-9]+(ns|us|ms|s|m|h)$\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSo with \u003ccode\u003e10s\u003c/code\u003e you can define the duration of 10 seconds and with \u003ccode\u003e2h\u003c/code\u003e you can say 2 hours.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_endpoint\"\u003eEndpoint\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ccode\u003eEndpoint\u003c/code\u003e type defines the properties required for communication with an endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf only the URL needs to be set, you can specify it as a string. If additional properties are required, the following options are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eurl\u003c/code\u003e\u003c/strong\u003e \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe URL of the endpoint. Depending on the mechanism, the URL can be templated.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIf templating is used, the user info, scheme, and host parts of the URL cannot be templated. Attempts to do so will result in runtime errors.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eTLS is enforced unless heimdall is started with the \u003ccode\u003e--insecure-skip-egress-tls-enforcement\u003c/code\u003e flag, which allows insecure communication with any configured service.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emethod\u003c/code\u003e\u003c/strong\u003e \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe HTTP method to use while communicating with the endpoint. If not set \u003ccode\u003ePOST\u003c/code\u003e is used.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eretry\u003c/code\u003e\u003c/strong\u003e \u003cem\u003e\u003ca href=\"#_retry\"\u003eRetry\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhat to do if the communication fails. If not configured, no retry attempts are done.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauth\u003c/code\u003e\u003c/strong\u003e \u003cem\u003e\u003ca href=\"#_authentication_strategy\"\u003eAuthentication Strategy\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAuthentication strategy to apply, if the endpoint requires authentication.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheaders\u003c/code\u003e\u003c/strong\u003e \u003cem\u003emap of strings\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHTTP headers to be sent to the endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThese headers are not analyzed by heimdall and are just forwarded to the endpoint. E.g. if you configure the \u003ccode\u003eContent-Encoding\u003c/code\u003e to something like \u003ccode\u003egzip\u003c/code\u003e, the service behind the used endpoint might fail to answer, as it would expect the body to be compressed.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehttp_cache\u003c/code\u003e\u003c/strong\u003e \u003cem\u003eobject\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eControls whether HTTP caching according to \u003ca href=\"https://www.rfc-editor.org/rfc/rfc7234\"\u003eRFC 7234\u003c/a\u003e should be used. To support this, that object defines the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eenabled\u003c/code\u003e\u003c/strong\u003e \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefaults to \u003ccode\u003efalse\u003c/code\u003e if not otherwise stated in the description of the configuration type, making use of the \u003ccode\u003eendpoint\u003c/code\u003e property. If set to \u003ccode\u003etrue\u003c/code\u003e heimdall will strictly follow the requirements from RFC 7234 and cache the responses if possible and reuse these if still valid.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies how long heimdall should cache the response if the endpoint referenced by the URL does not provide any explicit expiration time (no heuristic freshness lifetime is calculated). Without configuring this property, heimdall treats such responses as not cacheable. Defaults to \u003ccode\u003e0s\u003c/code\u003e if not otherwise stated in the description of the configuration type making use of the \u003ccode\u003eendpoint\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 16. Endpoint configuration as string\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003ehttps://foo.bar\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 17. Structured Endpoint configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar\u003c/span\u003e\n\u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n\u003cspan class=\"na\"\u003eretry\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1s\u003c/span\u003e\n\u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecookie\u003c/span\u003e\n\u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eX-My-First-Header\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\n \u003cspan class=\"na\"\u003eX-My-Second-Header\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebarfoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003ehttp_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_errorstate_type\"\u003eError/State Type\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall defines a couple of error/state types, which it uses to signal errors. Those, which are marked with (*) are available in CEL expressions. All can be used to define overrides for the HTTP response codes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing types are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eaccepted\u003c/code\u003e - this is the only state type in this list and is used to signal, the matched decision pipeline has been executed successfully, so the request can be forwarded to the upstream service. The response of that type results by default in a \u003ccode\u003e200 OK\u003c/code\u003e response.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eauthentication_error\u003c/code\u003e (*) - used if an authenticator failed to verify authentication data available in the request. E.g. an authenticator was configured to verify a JWT and the signature of it was invalid. If none of the authenticators used in a pipeline were able to authenticate the user, and the default error handler was used to handle such error, it will by default result in a \u003ccode\u003e401 Unauthorized\u003c/code\u003e response.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eauthorization_error\u003c/code\u003e (*) - used if an authorizer failed to authorize the subject. E.g. an authorizer is configured to use an expression on the given subject and request context, but that expression returned with an error. Error of this type results by default in \u003ccode\u003e403 Forbidden\u003c/code\u003e response if the default error handler was used to handle such error.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ecommunication_error\u003c/code\u003e (*) - this error is used to signal a communication error while communicating to a remote system during the execution of the pipeline of the matched rule. Timeouts of DNSs errors result in such an error. Error of this type results by default in \u003ccode\u003e502 Bad Gateway\u003c/code\u003e HTTP code if handled by the default error handler.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003einternal_error\u003c/code\u003e - used if heimdall run into an internal error condition while processing the request. E.g. something went wrong while unmarshalling a JSON object, or if there was a configuration error, which couldn’t be raised while loading a rule, etc. Results by default in \u003ccode\u003e500 Internal Server Error\u003c/code\u003e response to the caller.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eno_rule_error\u003c/code\u003e - this error is used to signal, there is no matching rule to handle the given request. Error of this type results by default in \u003ccode\u003e404 Not Found\u003c/code\u003e HTTP code.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eprecondition_error\u003c/code\u003e (*) - used if the request does not contain required/expected data. E.g. if an authenticator could not find a cookie configured. Error of this type results by default in \u003ccode\u003e400 Bad Request\u003c/code\u003e HTTP code if handled by the default error handler.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_key_store\"\u003eKey Store\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis type configures a key store holding keys and corresponding certificate chains. PKCS#1, as well as PKCS#8 encodings are supported for private keys.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhile loading a key store following verifications are done:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eUniqueness of key ids and rejection of key stores which violate this condition (see also \u003ca href=\"#_key_id_lookup\"\u003eKey-Id Lookup\u003c/a\u003e)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCorrelation of keys and certificates to build a valid certificate chain for every given key if certificates are present. If the correlation fails, an error is raised and heimdall will refuse to start.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCertificate chain validation. If the chain is invalid, an error is raised and heimdall will refuse to start.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing configuration properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epath\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe path to the PEM file with the cryptographic material. Watching for secrets rotation is supported.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epassword\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the key material is protected with a password, this property can be set to decipher it. Password protection is only supported for PKCS#8 encoded keys\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf the key store contains multiple keys and these keys are password protected, same password must be used for all of these.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 18. Example configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/keystore.pem\u003c/span\u003e\n\u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVeryInsecure!\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_respond\"\u003eRespond\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis type enables instructing heimdall to preserve error information and provide it in the response body to the caller, as well as to use HTTP status codes deviating from those heimdall would usually use. The configuration, which can be done using this type affects only the behavior of the default error handler.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003everbose\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property you can instruct heimdall to preserve error information and provide it in the response body to the caller. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall supports MIME type negotiation. So, if the client sets the HTTP \u003ccode\u003eAccept\u003c/code\u003e header to e.g. \u003ccode\u003eapplication/json\u003c/code\u003e, and Heimdall run into an unhandled internal error condition, in addition to responding with \u003ccode\u003e500 Internal Server Error\u003c/code\u003e, it will render an error message, like shown below, if \u003ccode\u003everbose\u003c/code\u003e has been set to \u003ccode\u003etrue\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;code\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;internal error\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;whatever led to the error\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ccode\u003emessage\u003c/code\u003e will however contain just high-level information, like \u0026#34;failed to parse something\u0026#34;, but will not contain any stack traces.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewith\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eResponseOverride set\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis property enables mapping between response/error types used by heimdall and the corresponding HTTP status codes. Each entry must be from the list of the supported \u003ca href=\"#_errorstate_type\"\u003eError/State Types\u003c/a\u003e and contain exactly one property named \u003ccode\u003ecode\u003c/code\u003e, which then defines the desired mapping.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 19. Making error responses verbose and changing the HTTP codes for some errors\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003everbose\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\u003cspan class=\"na\"\u003ewith\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e404\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e404\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_retry\"\u003eRetry\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImplements an exponential backoff strategy for endpoint communication. It increases the backoff exponentially by multiplying the \u003ccode\u003emax_delay\u003c/code\u003e with 2^(attempt count)\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003egive_up_after\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSets an upper bound on the maximum time to wait between two requests. Default to 0, which means no upper bound.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_delay\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe initial backoff.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 20. Retry configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example the backoff will be 1, 2, 4, 8, 16, 32, 60, …​\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e60s\u003c/span\u003e\n\u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_scopes_matcher\"\u003eScopes Matcher\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eScopes matcher is a configuration type allowing configuration of different strategies to match required scopes. In its simplest shape it can be just an array of strings (implemented by the \u003ca href=\"#_exact\"\u003eExact\u003c/a\u003e) scope matcher. To cover many use cases, different strategies are available and described in the following sections.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRegardless of the strategy, each matcher can explicitly be configured and supports the following configuration properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ematching_strategy\u003c/code\u003e - the type of the mathing strategy.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003evalues\u003c/code\u003e - the list of scope patterns\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_exact\"\u003eExact\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis the simplest matcher and is automatically selected, if just an array of strings is configured as shown in the following snippet:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHowever, as written in the \u003ca href=\"#_scopes_matcher\"\u003eScopes Matcher\u003c/a\u003e section, it can also explicitly be selected by setting \u003ccode\u003ematching_strategy\u003c/code\u003e to \u003ccode\u003eexact\u003c/code\u003e and defining the required scopes in the \u003ccode\u003evalues\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 21. Essentially same configurations\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ematching_strategy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n\u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_hierarchic\"\u003eHierarchic\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis matcher enables matching hierarchical scopes, which use \u003ccode\u003e.\u003c/code\u003e as separator. Imagine your system is organized that way, that it defines namespaces for different services like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emy-service\u003c/code\u003e being the top namespace\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emy-service.booking\u003c/code\u003e - being the namespace of the booking service\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emy-service.orders\u003c/code\u003e - being the namespace of the orders service\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emy-service.orders.partners\u003c/code\u003e - being the namespace of the order service for partners and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emy-service.orders.customers\u003c/code\u003e - being the namespace of the order service for customers\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBasically you’ve established an identity for each of your services (this is comparable to how \u003ca href=\"https://spiffe.io/docs/latest/spiffe-about/spiffe-concepts/#spiffe-id\"\u003eSPIFFE IDs\u003c/a\u003e are organized and also used for).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNow, imagine you use these namespaces as scope values to limit the usage of the issued tokens. In such situations the hierarchic scope matcher can become handy if you would like to assert any scope of the token must be in e.g. the \u003ccode\u003emy-service\u003c/code\u003e or the \u003ccode\u003emy-service.orders\u003c/code\u003e namespace.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis matcher can only be used by explicitly setting the \u003ccode\u003ematching_strategy\u003c/code\u003e to \u003ccode\u003ehierarchic\u003c/code\u003e and defining the required patterns in the \u003ccode\u003evalues\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 22. Matching of hierarchic scopes\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ematching_strategy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehierarchic\u003c/span\u003e\n\u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003emy-service\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis configuration will ensure all scopes withing the scope or scp claim are within the \u003ccode\u003emy-service\u003c/code\u003e namespace. So scope claim like\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;scope\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;my-service.orders\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;my-service.orders.customers\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ewould match, but\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;scope\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;not-my-service\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;my-service.orders.customers\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ewould not match.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_wildcard\"\u003eWildcard\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis matcher enables matching scopes using wildcards. It goes beyond the \u003ca href=\"#_hierarchic\"\u003eHierarchic\u003c/a\u003e scope matcher by enabling usage of wildcards.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis matcher can only be used by explicitly setting the \u003ccode\u003ematching_strategy\u003c/code\u003e to \u003ccode\u003ewildcard\u003c/code\u003e and defining the required patterns in the \u003ccode\u003evalues\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_session_lifespan\"\u003eSession Lifespan\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis configuration type enables the configuration of session lifespans, used for session validation for those authenticators, which act on non-standard protocols. Following properties are available.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eactive\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the field describing the \u0026#34;active\u0026#34; status of the session in the corresponding JSON object. The actual value in that field should be convertable to a \u003ccode\u003ebool\u003c/code\u003e type. If not provided, or not found in the session object, the session is considered to be \u0026#34;active\u0026#34;. \u0026#34;active\u0026#34; means it can be used and represent a valid session between the authentication system and the subject, the session has been issued to.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eissued_at\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the field in the corresponding JSON object, describing the time, when the session object has been issued. If not provided or not found, the issuance time is not considered during session validation.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003enot_before\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the field in the corresponding JSON object describing the time, until which the session object is not allowed to be used. If not provided or not found, the corresponding time is not considered during session validation.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003enot_after\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the field in the corresponding JSON object describing the time, after which the session object is not allowed to be used. If not provided or not found, the corresponding time is not considered during session validation.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etime_format\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince different authentication system use different representations for time strings, this property allows the definition of the \u003ca href=\"https://pkg.go.dev/time#pkg-constants\"\u003etime format/layout\u003c/a\u003e used by the authentication system. Defaults to Unix Epoch time stamp.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nYou can use the following \u003ca href=\"https://go.dev/play/p/VjtvWMmp-Ua\"\u003eGo Playground\u003c/a\u003e link to test your time format settings.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalidity_leeway\u003c/code\u003e\u003c/strong\u003e: \u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables definition of an allowed time drift between the authentication system and heimdall for the validation of the session validity. Defaults to 0.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 23. Making use of session information received from Ory’s Kratos\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA typical response from Kratos\u0026#39; \u003ccode\u003ewhoami\u003c/code\u003e endpoint looks like follows (stripped to the most interesting parts):\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1338410d-c473-4503-a96a-53efa06e2531\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;active\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;expires_at\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;2021-10-15T15:58:57.683338Z\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;authenticated_at\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;2021-10-14T15:58:57.683338Z\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;issued_at\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;2021-10-14T15:58:57.683338Z\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;identity\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;9496bbd5-f426-473f-b087-c7df853f274a\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"err\"\u003e...\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable usage of these properties in Heimdall, you can configure the Session Lifespan as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eactive\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eactive\u003c/span\u003e\n\u003cspan class=\"na\"\u003eissued_at\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eissued_at\u003c/span\u003e\n\u003cspan class=\"na\"\u003enot_before\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticated_at\u003c/span\u003e\n\u003cspan class=\"na\"\u003enot_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexpires_at\u003c/span\u003e\n\u003cspan class=\"na\"\u003etime_format\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e2006-01-02T15:04:05.999999Z07\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003evalidity_leeway\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 24. Making use of session information received from a compliant OAuth2 authorization service\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA typical response from a token \u003ccode\u003eintrospection\u003c/code\u003e endpoint looks like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;active\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;client_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;l238j323ds-23ij4\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;username\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;jdoe\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;scope\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;read write dolphin\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;sub\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Z5O3upPC88QrAjx00dis\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;aud\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://protected.example.net/resource\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;iss\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://server.example.com/\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;exp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1419356238\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;iat\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1419350238\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;extension_field\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;twenty-seven\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable usage of these properties in Heimdall, you can configure the Session Lifespan as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eactive\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eactive\u003c/span\u003e\n\u003cspan class=\"na\"\u003eissued_at\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eiat\u003c/span\u003e\n\u003cspan class=\"na\"\u003enot_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexp\u003c/span\u003e\n\u003cspan class=\"na\"\u003evalidity_leeway\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs you see, there is no need to define the time format as the times values appearing in the responses from an introspection endpoint are Unix Epoch time stamps.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_signer\"\u003eSigner\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhen heimdall is used to issue signed objects, like JWTs, to enable upstream services to rely on authentic information, it acts as an issuer of such objects and requires corresponding configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name used to specify the issuer. E.g. if a JWT is generated, this value is used to set the \u003ccode\u003eiss\u003c/code\u003e claim. If not set, the value \u003ccode\u003eheimdall\u003c/code\u003e is used.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ekey_store\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_key_store\"\u003eKey Store\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe key store containing the cryptographic material. At least one private key must be present.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ekey_id\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003ekey_store\u003c/code\u003e contains multiple keys, this property can be used to specify the key to use (see also \u003ca href=\"/docs/configuration/types/#_key_id_lookup\"\u003eKey-Id Lookup\u003c/a\u003e). If not specified, the first key is used. If specified, but there is no key for the given key id present, an error is raised and heimdall will refuse to start.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 25. Possible configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you have a PEM file located in \u003ccode\u003e/opt/heimdall/keystore.pem\u003c/code\u003e with the following contents:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"txt\"\u003e-----BEGIN EC PRIVATE KEY-----\nX-Key-ID: foo\n\nMIGkAgEBBDBRLr783dIM5NHJnDDMRVBiFSF56xqHle5lZk1ZCyyow9wKZGuF4EWK\njRBISBkE3NSgBwYFK4EEACKhZANiAAQ+oGUOJpVjntIWuanYxpXe6oN5tKhzLhBX\nGP1SOXiLhnPNnN2uZu9KwOoBzoZhr/Fxw+sziXmzHJwjluz78VOlFKyopxTfmxRZ\n0qq3f/KHWdDtVvmTfT0O/ux9mg6mCJw=\n-----END EC PRIVATE KEY-----\n-----BEGIN CERTIFICATE-----\nMIIByjCCAVGgAwIBAgIBATAKBggqhkjOPQQDAzAuMQswCQYDVQQGEwJFVTENMAsG\nA1UEChMEVGVzdDEQMA4GA1UEAxMHVGVzdCBDQTAeFw0yMjA4MTUwOTE3MTFaFw0y\nMjA4MTUxMDE3MTFaMDAxCzAJBgNVBAYTAkVVMQ0wCwYDVQQKEwRUZXN0MRIwEAYD\nVQQDEwlUZXN0IEVFIDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ+oGUOJpVjntIW\nuanYxpXe6oN5tKhzLhBXGP1SOXiLhnPNnN2uZu9KwOoBzoZhr/Fxw+sziXmzHJwj\nluz78VOlFKyopxTfmxRZ0qq3f/KHWdDtVvmTfT0O/ux9mg6mCJyjQTA/MA4GA1Ud\nDwEB/wQEAwIHgDAMBgNVHQ4EBQQDYmFyMB8GA1UdIwQYMBaAFLO77bgPgZMKz11D\nBVDUXvtNGeBnMAoGCCqGSM49BAMDA2cAMGQCMFRlx9Bq0MuSh5pDhDTqRq/MnxxD\nW7qZg15AXoNnLrR60vV9gHjzkp1UkcU9viRIuAIwU0BjwDncp9z1seqKh+/eJV3f\nxstQe2rzUEptWLIiPFoOBWZuw9wJ/Hunjik3a9T/\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIByjCCAVCgAwIBAgIBATAKBggqhkjOPQQDAzAuMQswCQYDVQQGEwJFVTENMAsG\nA1UEChMEVGVzdDEQMA4GA1UEAxMHVGVzdCBDQTAeFw0yMjA4MTUwOTE3MTFaFw0y\nMjA4MTYwOTE3MTFaMC4xCzAJBgNVBAYTAkVVMQ0wCwYDVQQKEwRUZXN0MRAwDgYD\nVQQDEwdUZXN0IENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEf96tstMNdNoNfYjl\nbGY6BvBFTsl9E3hpPnta7SJn6BqIYz6KEohDJ+8DXwUMVb5Ytr/QkEikg966HCY3\nA9TFBUdAs01TV8f2KoAPRQVrh+ccSLLJyACENfZ5VbGSQ0wso0IwQDAOBgNVHQ8B\nAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUs7vtuA+BkwrPXUMF\nUNRe+00Z4GcwCgYIKoZIzj0EAwMDaAAwZQIxAMPgE/Z+1Dcj+lH7jioE16Hig0HQ\nFC4qBx1UU05H05Gs23ECB1hzD2qXikVpaNyuDgIwbogEu42wIwpDa5xdJIZcIhmz\nDIuPvEscUDjU3C+1GPxmACcRMPv9QVUEcBAvZkfn\n-----END CERTIFICATE-----\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThen you can configure heimdall to use it like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/opt/heimdall/keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_subject\"\u003eSubject\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis configuration type enables extraction of subject information from responses received by Heimdall from authentication services. Following properties are available.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eid\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the id of the subject in the JSON object.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eattributes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the attributes of the subject in the JSON object. Defaults to \u003ccode\u003e@this\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 26. Extracting subject id from an \u003ca href=\"https://tools.ietf.org/html/rfc7662\"\u003eOAuth2 Introspection\u003c/a\u003e endpoint response.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example shows how to extract the subject id from an \u003ca href=\"https://tools.ietf.org/html/rfc7662\"\u003eOAuth2 Introspection\u003c/a\u003e endpoint response and set the subject attributes to the entire response\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esub\u003c/span\u003e\n\u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"err\"\u003e@\u003c/span\u003e\u003cspan class=\"s\"\u003ethis\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSetting \u003ccode\u003eattributes\u003c/code\u003e was actually not required, as \u003ccode\u003e@this\u003c/code\u003e would be set by default anyway.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 27. Extracting subject id from an \u003ca href=\"https://www.ory.sh/docs/kratos/\"\u003eOry Kratos\u003c/a\u003e \u0026#34;whoami\u0026#34; endpoint response\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example shows how to extract the subject id from an \u003ca href=\"https://www.ory.sh/docs/kratos/\"\u003eOry Kratos\u003c/a\u003e \u0026#34;whoami\u0026#34; endpoint response and set the subject attributes to the entire response. \u003ccode\u003eattributes\u003c/code\u003e is not configured, so default is used.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eidentity.id\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_tls\"\u003eTLS\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing are the supported TLS configuration properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ekey_store\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_key_store\"\u003eKey Store\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe key store containing the cryptographic material. At least one private key and the corresponding certificate must be present.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ekey_id\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003ekey_store\u003c/code\u003e contains multiple keys, this property can be used to specify the key to use (see also \u003ca href=\"#_key_id_lookup\"\u003eKey-Id Lookup\u003c/a\u003e). If not specified, the first key is used. If specified, but there is no key for the given key id present, an error is raised and heimdall will refuse to start.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emin_version\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe minimal TLS version to support. Can be either \u003ccode\u003eTLS1.2\u003c/code\u003e or \u003ccode\u003eTLS1.3\u003c/code\u003e. Defaults to \u003ccode\u003eTLS1.3\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecipher_suites\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCan be configured if \u003ccode\u003emin_version\u003c/code\u003e is set to \u003ccode\u003eTLS1.2\u003c/code\u003e. If \u003ccode\u003emin_version\u003c/code\u003e is set to \u003ccode\u003eTLS1.3\u003c/code\u003e the configured values are ignored. Only the following PFS cipher suites are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefaults to the last six cipher suites if \u003ccode\u003emin_version\u003c/code\u003e is set to \u003ccode\u003eTLS1.2\u003c/code\u003e and \u003ccode\u003ecipher_suites\u003c/code\u003e is not configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 28. Example configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVeryInsecure!\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\n\u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\n\u003cspan class=\"na\"\u003ecipher_suites\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_key_id_lookup\"\u003eKey-Id Lookup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhen heimdall loads a key store, following algorithm is used to get the key id for the key:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eif the PEM entry with the private key has \u003ccode\u003eX-Key-ID\u003c/code\u003e header specified, this value is used as key id\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOtherwise, if an X.509 certificate is present for the private key, and it has the \u003ccode\u003eSubject Key Identifier\u003c/code\u003e extension set, the hex representation of it is used as key id.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOtherwise, heimdall calculates the value for the \u003ccode\u003eSubject Key Identifier\u003c/code\u003e according to \u003ca href=\"https://www.ietf.org/rfc/rfc3280.html#section-4.2.1.2\"\u003eRFC 3280, Section 4.2.1.2\u003c/a\u003e and uses hex representation of it as key id.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Configuration Reference"],"tags":null,"title":"Type Definitions","url":"/docs/configuration/types/"},{"categories":null,"content":" Below you can find possible contents (not exhaustive) for Heimdall’s config.yaml file. Head over to configuration documentation to get detailed explanation.\nserve: host: 127.0.0.1 port: 4469 respond: verbose: true with: authorization_error: code: 404 authentication_error: code: 404 timeout: read: 2s write: 5s idle: 2m connections_limit: max_per_host: 10 max_idle: 100 max_idle_per_host: 50 buffer_limit: read: 10KB write: 10KB cors: allowed_origins: - example.org allowed_methods: - GET - POST allowed_headers: - Authorization exposed_headers: - X-My-Header allow_credentials: true max_age: 1m tls: key_store: path: /path/to/key/store.pem password: VerySecure! key_id: first_entry min_version: TLS1.2 cipher_suites: - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 trusted_proxies: - 192.168.1.0/24 management: host: 127.0.0.1 port: 4457 timeout: read: 2s write: 5s idle: 2m cors: allowed_origins: - example.org allowed_methods: - GET - POST allowed_headers: - Authorization exposed_headers: - X-My-Header allow_credentials: true max_age: 1m tls: key_store: path: /path/to/key/store.pem min_version: TLS1.2 cache: type: redis-sentinel config: db: 2 master: whatever nodes: - foo:1234 - bar:1234 credentials: path: /path/to/credentials.yaml tls: key_store: path: /path/to/redis_client_keystore.pem key_id: bf5d129a7fec8b1fde11eab459784cc2f14e6c1d min_version: TLS1.2 cipher_suites: - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 client_cache: ttl: 10m max_flush_delay: 20us secrets_reload_enabled: true log: level: debug format: text tracing: enabled: true span_processor: batch metrics: enabled: true profiling: enabled: false host: 0.0.0.0 port: 9000 mechanisms: authenticators: - id: anonymous_authenticator type: anonymous - id: unauthorized_authenticator type: unauthorized - id: foo type: basic_auth config: user_id: bar password: baz allow_fallback_on_error: true - id: kratos_session_authenticator type: generic config: identity_info_endpoint: url: https://127.0.0.1:4433/sessions/whoami auth: auth: type: basic_auth config: user: foo password: bar retry: max_delay: 300ms give_up_after: 2s authentication_data_source: - cookie: ory_kratos_session forward_cookies: - ory_kratos_session subject: attributes: \u0026#34;@this\u0026#34; id: \u0026#34;identity.id\u0026#34; allow_fallback_on_error: true - id: hydra_authenticator type: oauth2_introspection config: introspection_endpoint: url: https://hydra:4445/oauth2/introspect retry: max_delay: 300ms give_up_after: 2s auth: type: api_key config: in: header name: X-Api-Key value: VerySecret! token_source: - header: Authorization scheme: Bearer - query_parameter: access_token - body_parameter: access_token assertions: issuers: - https://127.0.0.1:4444/ scopes: - foo - bar audience: - bla subject: attributes: \u0026#34;@this\u0026#34; id: \u0026#34;sub\u0026#34; allow_fallback_on_error: true - id: jwt_authenticator type: jwt config: metadata_endpoint: url: https://auth-server/.well-known/oauth-authorization-server disable_issuer_identifier_verification: true http_cache: enabled: true cache_ttl: 1h jwt_source: - header: Authorization scheme: Bearer - query_parameter: access_token - body_parameter: access_token assertions: audience: - bla scopes: - foo allowed_algorithms: - RS256 subject: attributes: \u0026#34;@this\u0026#34; id: \u0026#34;identity.id\u0026#34; cache_ttl: 5m allow_fallback_on_error: true authorizers: - id: allow_all_authorizer type: allow - id: deny_all_authorizer type: deny - id: remote_authorizer type: remote config: endpoint: url: https://my-authz-system/{{ .Values.some-key }} method: POST headers: foo-bar: \u0026#34;{{ .Subject.ID }}\u0026#34; auth: type: api_key config: in: header name: X-API-Key value: super duper secret values: some-key: some-value payload: \u0026#34;https://bla.bar\u0026#34; expressions: - expression: | Payload.response == true forward_response_headers_to_upstream: - bla-bar - id: user_is_admin_authz type: cel config: expressions: - expression: \u0026#34;\u0026#39;admin\u0026#39; in Subject.Attributes.groups\u0026#34; contextualizers: - id: subscription_contextualizer type: generic config: endpoint: url: https://foo.bar method: GET headers: bla: bla auth: type: oauth2_client_credentials config: auth_method: request_body token_url: https://bar.foo client_id: foo client_secret: bar cache_ttl: 20s header: name: X-Foo scheme: Bar payload: foo - id: profile_data_contextualizer type: generic config: endpoint: url: https://profile headers: foo: bar continue_pipeline_on_error: true finalizers: - id: jwt type: jwt config: signer: name: foobar key_store: path: /opt/heimdall/keystore.pem password: VeryInsecure! key_id: foo ttl: 5m header: name: Foo scheme: Bar claims: \u0026#34;{\u0026#39;user\u0026#39;: {{ quote .Subject.ID }} }\u0026#34; - id: bla type: header config: headers: foo-bar: bla - id: blabla type: cookie config: cookies: foo-bar: \u0026#39;{{ .Subject.ID }}\u0026#39; - id: get_token type: oauth2_client_credentials config: header: name: X-Token token_url: https://my-oauth-provider.com/token client_id: my_client client_secret: VerySecret! auth_method: basic_auth cache_ttl: 5m scopes: - foo - bar error_handlers: - id: default type: default - id: authenticate_with_kratos type: redirect config: to: https://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }} default_rule: backtracking_enabled: false execute: - authenticator: anonymous_authenticator - finalizer: jwt on_error: - error_handler: authenticate_with_kratos if: | ((type(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;kratos_session_authenticator\u0026#34;) || type(Error) == authorization_error) \u0026amp;\u0026amp; Request.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;*/*\u0026#34;) providers: file_system: src: test_rules.yaml watch: true http_endpoint: watch_interval: 5m endpoints: - url: https://foo.bar/ruleset1 http_cache: enabled: false - url: https://foo.bar/ruleset2 retry: give_up_after: 5s max_delay: 250ms auth: type: api_key config: name: api_key value: super-secret in: cookie header: X-Customer-Header: Some Value cloud_blob: watch_interval: 1m buckets: - url: gs://my-bucket prefix: service1 - url: azblob://my-bucket prefix: service2 - url: s3://my-bucket/my-rule-set kubernetes: auth_class: foo tls: key_id: foo key_store: path: /path/to/pem.file password: VerySecret! min_version: TLS1.3 ","description":"","html_content":"\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBelow you can find possible contents (not exhaustive) for Heimdall’s \u003ccode\u003econfig.yaml\u003c/code\u003e file. Head over to configuration documentation to get detailed explanation.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eserve\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4469\u003c/span\u003e\n \u003cspan class=\"na\"\u003erespond\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003everbose\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewith\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e404\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e404\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2m\u003c/span\u003e\n \u003cspan class=\"na\"\u003econnections_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_per_host\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e10\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_idle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e100\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_idle_per_host\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e50\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuffer_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10KB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10KB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecors\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_origins\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eexample.org\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_methods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePOST\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexposed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eX-My-Header\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_credentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_age\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1m\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/key/store.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecure!\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efirst_entry\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecipher_suites\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\u003c/span\u003e\n \u003cspan class=\"na\"\u003etrusted_proxies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e192.168.1.0/24\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emanagement\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4457\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2m\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecors\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_origins\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eexample.org\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_methods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePOST\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexposed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eX-My-Header\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_credentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_age\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1m\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/key/store.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredis-sentinel\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003edb\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e2\u003c/span\u003e\n \u003cspan class=\"na\"\u003emaster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ewhatever\u003c/span\u003e\n \u003cspan class=\"na\"\u003enodes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo:1234\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar:1234\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecredentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/credentials.yaml\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/redis_client_keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebf5d129a7fec8b1fde11eab459784cc2f14e6c1d\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecipher_suites\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10m\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_flush_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e20us\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003esecrets_reload_enabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edebug\u003c/span\u003e\n \u003cspan class=\"na\"\u003eformat\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etext\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003espan_processor\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebatch\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emetrics\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eprofiling\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e0.0.0.0\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e9000\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eunauthorized_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eunauthorized\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebaz\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_fallback_on_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekratos_session_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidentity_info_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4433/sessions/whoami\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003eretry\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e300ms\u003c/span\u003e\n \u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_data_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ecookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eory_kratos_session\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_cookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eory_kratos_session\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@this\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eidentity.id\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_fallback_on_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehydra_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_introspection\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eintrospection_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://hydra:4445/oauth2/introspect\u003c/span\u003e\n \u003cspan class=\"na\"\u003eretry\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e300ms\u003c/span\u003e\n \u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Api-Key\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecret!\u003c/span\u003e\n \u003cspan class=\"na\"\u003etoken_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003equery_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ebody_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4444/\u003c/span\u003e\n \u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaudience\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@this\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003esub\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_fallback_on_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emetadata_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://auth-server/.well-known/oauth-authorization-server\u003c/span\u003e\n \u003cspan class=\"na\"\u003edisable_issuer_identifier_verification\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1h\u003c/span\u003e\n \u003cspan class=\"na\"\u003ejwt_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003equery_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ebody_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaudience\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\n \u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_algorithms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eRS256\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@this\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eidentity.id\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_fallback_on_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow_all_authorizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all_authorizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote_authorizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://my-authz-system/{{ .Values.some-key }}\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ePOST\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efoo-bar\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-API-Key\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esuper duper secret\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esome-key\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esome-value\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://bla.bar\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.response == true\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_response_headers_to_upstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebla-bar\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003euser_is_admin_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#39;admin\u0026#39;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ein\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eSubject.Attributes.groups\u0026#34;\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003econtextualizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esubscription_contextualizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebla\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_client_credentials\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_method\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erequest_body\u003c/span\u003e\n \u003cspan class=\"na\"\u003etoken_url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://bar.foo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_secret\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e20s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Foo\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBar\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eprofile_data_contextualizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://profile\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efoo\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtinue_pipeline_on_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/opt/heimdall/keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVeryInsecure!\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eFoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBar\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclaims\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e{\u0026#39;user\u0026#39;:\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efoo-bar\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eblabla\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecookie\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efoo-bar\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eget_token\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_client_credentials\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Token\u003c/span\u003e\n \u003cspan class=\"na\"\u003etoken_url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://my-oauth-provider.com/token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy_client\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_secret\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecret!\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_method\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eerror_handlers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticate_with_kratos\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }}\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003edefault_rule\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebacktracking_enabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous_authenticator\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003eon_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticate_with_kratos\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e((type(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;kratos_session_authenticator\u0026#34;) ||\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) == authorization_error) \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eRequest.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;*/*\u0026#34;)\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eproviders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etest_rules.yaml\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003ehttp_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch_interval\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar/ruleset1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar/ruleset2\u003c/span\u003e\n \u003cspan class=\"na\"\u003eretry\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e250ms\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esuper-secret\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecookie\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eX-Customer-Header\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSome Value\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003ecloud_blob\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch_interval\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1m\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuckets\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egs://my-bucket\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservice1\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eazblob://my-bucket\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservice2\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003es3://my-bucket/my-rule-set\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003ekubernetes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_class\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/pem.file\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecret!\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.3\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Configuration Reference"],"tags":null,"title":"Reference","url":"/docs/configuration/reference/"}] \ No newline at end of file +[{"categories":null,"content":" What is heimdall? Heimdall is a cloud native identity aware proxy and access control decision service inspired by the Zero Trust idea. It brings together authentication and authorization systems and can be thought as an orchestrator for these in front of your services, allowing however completely retaining control even without the need for any type of maintenance in your own code.\nYou can use it\nintegrated into available proxies and API gateways, allowing implementation of Edge-level Authorization Architectures, or\nstand alone as an authentication \u0026amp; authorization proxy\nBoth approaches can help you scaling and securing you services by transparently adding security capabilities and secure defaults related to authentication and authorization.\nIf you want to know more about Edge-level Authorization Architecture, the Blog post from Netflix is a highly recommended read Typical challenges A typical (monolithic) system, or named it service, has not only to deal with the actual business logic, but also with authentication and authorization requirements (among other non-functional requirements) as depicted in the figure below.\nFigure 1. A typical monolithic system What do we have here?\nTo cover authentication requirements, that service will make use of some identity management system to verify the request authentication status.\nThe existing authorization requirements will most probably result in if else statements in code. Even such approaches are straight forward and easy to implement on the first sight, these are not easy to maintain and have many drawbacks (e.g. testing of particular use cases), and it becomes even more challenging when entering microservices.\nHow does it look then if we have microservices?\nNot every microservice will hold the entire information required for authorization purposes.\nSo, there will be a need to communicate to other services to get the required contextual information about the authenticated subject to be able to take the required authorization decision.\nThe management and maintenance of the authorization requirements will become even more challenging, as the implementation of these will usually be scattered across many services.\nTo overcome these dependencies, organizations either start pushing that contextual information into the identity management system, making it a god system with all resulting negative effects, or start using special purpose authorization systems, allowing managing the corresponding authorization policies outside the code.\nEven that approach reduces dependencies between the services and also the time to market, it introduces a new dependency, which all, or almost all services must make use of. And, most probably, the authorization system will also need to somehow retrieve contextual information for authorization policy evaluation purposes.\nAnd we just started to scratch the top of the iceberg. What if our system, comprised from these microservices is implemented in different languages? Even there are many libraries and also frameworks addressing authentication challenges, usually we just want to make the lives of our developers easier by providing components, which work the same way for each and every language. So the setup depicted above, well become similar to the one depicted below.\nFigure 2. Typical microservice deployment scenario Here, a new authentication proxy, typically deployed as a sidecar with each microservice (sometimes also as a central proxy), is introduced taking over the responsibility for the existing authentication challenges and unifying the corresponding implementation. But there are still many drawbacks and limitations, like those addressed by the following questions\nWhat if there is a need to have multiple identity management systems, e.g. one for the customers and one for accessing administrative or backoffice related functionality of the system?\nWhat if there is a need to migrate from one authentication or authorization system to another?\nWhat if there is a need to open the existing APIs?\nWhat if there is a need to support multiple different clients, like browsers, like mobile apps, IoT devices, etc?\nWhat if the business decides to change the existing authorization requirements, like introduction of a new subscription model, or alike, which would require additional information about our user, resulting in yet another dependency to some further service?\nWhat if depending on the client, we need completely different authentication strategies or even protocols, like OAuth2 or OpenID Connect in one case, mTLS in another case and cookie based approach and yet another case?\nHow to ensure, that our microservice code does not implement shortcuts and thus does not compromise the security of the entire system? (And there are diverse options achieving that)\n…​\nThis is by far not an exhaustive list. But the main question related to it is what does all of that mean in sense of coordination-, implementation efforts and time-to-market?\nHeimdall to the Rescue This is exactly where heimdall can step in and help you to address these challenges, reduce the complexity of your code, free resources, increase your time to market and make your system more secure.\nIf you let heimdall care about most of the existing authentication and authorization challenges, our new setup would then look as depicted below.\nFigure 3. Heimdall based deployment scenario This way you let heimdall orchestrate existing authentication and authorization systems and also provide the information about the authenticated and authorized subjects to your microservice in a unified format completely independent of the used authentication strategy or protocol.\nThere is however still the need to perform some type of authorization logic in your microservice code. Especially if we talk about read requests (most probably you want to provide different representation of the requested resource based on the authorization status). But it is much simpler, and it gives you much more freedom compared to all previous approaches.\nYou don’t necessary need to replace proxies, gateways, ingress controller, or alike currently in place in your infrastructure with heimdall. You can easily integrate heimdall with them to achieve the functionality depicted above. How it works Heimdall intercepts all your application related HTTP(s) traffic, allowing a broad set of identity and application aware authentication and authorization features based on the rules you specify and deploy together with your particular service. These rules let heimdall route each request through a service or even endpoint specific authentication and authorization pipeline as depicted in diagram below.\nFigure 4. Authentication \u0026amp; Authorization Pipeline This pipeline ensures that, according to the needs of the particular backend service endpoint,\neach request is authenticated (so, you know who the subject of the request is) by making use of the available identity management systems,\nthe required contextual information about the subject is available (like e.g. current location based on IP, roles or groups membership information, etc.) by retrieving it from any possible API, so that\nthe subject can be and is authorized by your authorization system, or even directly by heimdall and\nthe information about the subject is transformed into a format, required by the backend service. So that despite the used authentication or authorization system or protocol, the subject information is always provided in the same stable representation to your microservice.\nNext Steps Take a look and experiment\nThe Protect an Application chapter describes two setups, allowing getting your hands \u0026#34;dirty\u0026#34; and familiarizing with the concepts implemented by heimdall.\nJoin the community\nChat interactively in our Discord and ask your questions :)\nLearn the concepts\nThere is an entire section which describes the concepts, users should understand. Start with Pipelines, which deals with the \u0026#34;Client Request Journey\u0026#34; depicted above in great detail and work you through until the Operating Modes, which will reveal you the possible integration options.\nCheck the guides\nMany guides have been written to support you in you endeavour with heimdall, including working examples, which you can find on GitHub. There are also many examples in particular chapters.\nImplement your requirements and bring heimdall to production\nInstall heimdall into your \u0026#34;playground\u0026#34; environment, implement rules by making use of mechanisms reflecting your requirements, secure your setup and bring it to production.\n","description":"This page gives an overview about heimdall, the challenges it addresses and how it does so. In addition, you can find some recommendations on where to look next.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_what_is_heimdall\"\u003eWhat is heimdall?\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall is a cloud native identity aware proxy and access control decision service inspired by the Zero Trust idea. It brings together authentication and authorization systems and can be thought as an orchestrator for these in front of your services, allowing however completely retaining control even without the need for any type of maintenance in your own code.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can use it\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eintegrated into available proxies and API gateways, allowing implementation of Edge-level Authorization Architectures, or\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003estand alone as an authentication \u0026amp; authorization proxy\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBoth approaches can help you scaling and securing you services by transparently adding security capabilities and secure defaults related to authentication and authorization.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you want to know more about Edge-level Authorization Architecture, the \u003ca href=\"https://netflixtechblog.com/edge-authentication-and-token-agnostic-identity-propagation-514e47e0b602\"\u003eBlog post\u003c/a\u003e from Netflix is a highly recommended read\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_typical_challenges\"\u003eTypical challenges\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA typical (monolithic) system, or named it service, has not only to deal with the actual business logic, but also with authentication and authorization requirements (among other non-functional requirements) as depicted in the figure below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-d2f5c648e6dd3a2376f4fc340284540c.svg\" alt=\"Diagram\" width=\"920\" height=\"518\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 1. A typical monolithic system\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhat do we have here?\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eTo cover authentication requirements, that service will make use of some identity management system to verify the request authentication status.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe existing authorization requirements will most probably result in if else statements in code. Even such approaches are straight forward and easy to implement on the first sight, these are not easy to maintain and have many drawbacks (e.g. testing of particular use cases), and it becomes even more challenging when entering microservices.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow does it look then if we have microservices?\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eNot every microservice will hold the entire information required for authorization purposes.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eSo, there will be a need to communicate to other services to get the required contextual information about the authenticated subject to be able to take the required authorization decision.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe management and maintenance of the authorization requirements will become even more challenging, as the implementation of these will usually be scattered across many services.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo overcome these dependencies, organizations either start pushing that contextual information into the identity management system, making it a god system with all resulting negative effects, or start using special purpose authorization systems, allowing managing the corresponding authorization policies outside the code.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEven that approach reduces dependencies between the services and also the time to market, it introduces a new dependency, which all, or almost all services must make use of. And, most probably, the authorization system will also need to somehow retrieve contextual information for authorization policy evaluation purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAnd we just started to scratch the top of the iceberg. What if our system, comprised from these microservices is implemented in different languages? Even there are many libraries and also frameworks addressing authentication challenges, usually we just want to make the lives of our developers easier by providing components, which work the same way for each and every language. So the setup depicted above, well become similar to the one depicted below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_fig_typical_deployment_scenario\" class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-2ad275416d51525f3aa30125819e84af.svg\" alt=\"Diagram\" width=\"1150\" height=\"518\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 2. Typical microservice deployment scenario\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, a new authentication proxy, typically deployed as a sidecar with each microservice (sometimes also as a central proxy), is introduced taking over the responsibility for the existing authentication challenges and unifying the corresponding implementation. But there are still many drawbacks and limitations, like those addressed by the following questions\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if there is a need to have multiple identity management systems, e.g. one for the customers and one for accessing administrative or backoffice related functionality of the system?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if there is a need to migrate from one authentication or authorization system to another?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if there is a need to open the existing APIs?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if there is a need to support multiple different clients, like browsers, like mobile apps, IoT devices, etc?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if the business decides to change the existing authorization requirements, like introduction of a new subscription model, or alike, which would require additional information about our user, resulting in yet another dependency to some further service?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhat if depending on the client, we need completely different authentication strategies or even protocols, like OAuth2 or OpenID Connect in one case, mTLS in another case and cookie based approach and yet another case?\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eHow to ensure, that our microservice code does not implement shortcuts and thus does not compromise the security of the entire system? (And there are diverse options achieving that)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e…​\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis is by far not an exhaustive list. But the main question related to it is what does all of that mean in sense of coordination-, implementation efforts and time-to-market?\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_heimdall_to_the_rescue\"\u003eHeimdall to the Rescue\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis is exactly where heimdall can step in and help you to address these challenges, reduce the complexity of your code, free resources, increase your time to market and make your system more secure.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you let heimdall care about most of the existing authentication and authorization challenges, our new setup would then look as depicted below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-3bcdc8fa896af7ae13650b8d7e6cf707.svg\" alt=\"Diagram\" width=\"890\" height=\"532\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 3. Heimdall based deployment scenario\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis way you let heimdall orchestrate existing authentication and authorization systems and also provide the information about the authenticated and authorized subjects to your microservice in a unified format completely independent of the used authentication strategy or protocol.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere is however still the need to perform some type of authorization logic in your microservice code. Especially if we talk about read requests (most probably you want to provide different representation of the requested resource based on the authorization status). But it is much simpler, and it gives you much more freedom compared to all previous approaches.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nYou don’t necessary need to replace proxies, gateways, ingress controller, or alike currently in place in your infrastructure with heimdall. You can easily integrate heimdall with them to achieve the functionality depicted above.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_how_it_works\"\u003eHow it works\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall intercepts all your application related HTTP(s) traffic, allowing a broad set of identity and application aware authentication and authorization features based on the rules you specify and deploy together with your particular service. These rules let heimdall route each request through a service or even endpoint specific authentication and authorization pipeline as depicted in diagram below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_fig_heimdall_request_pipeline\" class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-92616c018b7cc4e879c86947d2cf5d7c.svg\" alt=\"Diagram\" width=\"1290\" height=\"294\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 4. Authentication \u0026amp; Authorization Pipeline\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis pipeline ensures that, according to the needs of the particular backend service endpoint,\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eeach request is authenticated (so, you know who the subject of the request is) by making use of the available identity management systems,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe required contextual information about the subject is available (like e.g. current location based on IP, roles or groups membership information, etc.) by retrieving it from any possible API, so that\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe subject can be and is authorized by your authorization system, or even directly by heimdall and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe information about the subject is transformed into a format, required by the backend service. So that despite the used authentication or authorization system or protocol, the subject information is always provided in the same stable representation to your microservice.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_next_steps\"\u003eNext Steps\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eTake a look and experiment\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"/docs/getting_started/protect_an_app/\"\u003eProtect an Application\u003c/a\u003e chapter describes two setups, allowing getting your hands \u0026#34;dirty\u0026#34; and familiarizing with the concepts implemented by heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eJoin the community\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eChat interactively in our \u003ca href=\"https://discord.gg/qQgg8xKuyb\"\u003eDiscord\u003c/a\u003e and ask your questions :)\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eLearn the concepts\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere is an entire section which describes the concepts, users should understand. Start with \u003ca href=\"/docs/concepts/pipelines/\"\u003ePipelines\u003c/a\u003e, which deals with the \u0026#34;Client Request Journey\u0026#34; depicted above in great detail and work you through until the \u003ca href=\"/docs/concepts/operating_modes/\"\u003eOperating Modes\u003c/a\u003e, which will reveal you the possible integration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eCheck the guides\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eMany \u003ca href=\"/guides/\"\u003eguides\u003c/a\u003e have been written to support you in you endeavour with heimdall, including working examples, which you can find on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e. There are also many examples in particular chapters.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eImplement your requirements and bring heimdall to production\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"/docs/getting_started/installation/\"\u003eInstall\u003c/a\u003e heimdall into your \u0026#34;playground\u0026#34; environment, implement \u003ca href=\"/docs/rules/regular_rule/\"\u003erules\u003c/a\u003e by making use of \u003ca href=\"/docs/mechanisms/catalogue/\"\u003emechanisms\u003c/a\u003e reflecting your requirements, \u003ca href=\"/docs/operations/security/\"\u003esecure\u003c/a\u003e your setup and bring it to production.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Getting Started"],"tags":null,"title":"Discover heimdall","url":"/docs/getting_started/discover_heimdall/"},{"categories":null,"content":" Source Code You can always build a copy of heimdall by following the following instructions for your OS/environment.\nPrerequisites git\nThe Go programming language \u0026gt;= 1.24\nDownload Retrieve the latest copy of heimdall source code by cloning the git repository\n$ git clone git@github.com:dadrus/heimdall.git Build with go Build using a single line with go build\n$ CGO_ENABLED=0 go build -trimpath -ldflags=\u0026#34;-buildid= -w -s -X github.com/dadrus/heimdall/version.Version==my-custom-build\u0026#34; The flags are set by intention. Using -trimpath and -buildid= as part of the -ldflags argument ensures the build is reproducible (See also Reproducible Builds). Other flags remove unused symbols and debug information.\nBinary Prebuild binaries are available with every released version on GitHub, as well as for every merged PR to the main branch. The version of the latter is set to the git SHA1. Supported operating systems/architectures are:\ndarwin/amd64\ndarwin/arm64\nlinux/amd64\nlinux/arm64\nlinux/armv6\nlinux/armv7\nwindows/amd64\nFor Linux and Darwin the binaries are archived with tar.gz and for Windows with zip. All archives are signed (see also Verifying Heimdall Binaries and Container Images section on how to verify the signatures).\nDownload Retrieve the desired released version of heimdall binary for your operating system/architecture\nARCH=[your arch] OS=[your os] VERSION=[desired version] curl -L https://github.com/dadrus/heimdall/releases/download/${VERSION}/heimdall-${VERSION}-${OS}-${ARCH}.tar.gz \\ | tar -z -x Container Image Heimdall utilizes a minimal container multi-arch image which you can find on DockerHub, or on GHCR. As with Binary releases, heimdall can be pulled in several flavors. These are however currently limited to the Linux OS. Supported architectures are:\namd64\narm64\narm/v7\nAll container images are rootless - so heimdall will always run as a non-root user within the container. Since Heimdall does not have any dependencies, the images are distroless as well and contain only the binary of heimdall and the settings related to the OS user and group permissions, heimdall is running with.\nAs with the binary distribution, all container images are signed (see also Verifying Heimdall Binaries and Container Images section on how to verify the signatures).\nPrerequisites Docker, Podman, or other container runtime of your choice (examples are however using docker).\nPull Image The steps below will pull the images from DockerHub. If you want to pull them from GHCR, specify the ghcr.io registry in front of the repository.\nFollowing tag patterns exist:\nx.y.z[-\u0026lt;prerelease-identifier\u0026gt;] - will pull a specific tagged release.\n$ docker pull dadrus/heimdall:0.15.0 \u0026amp;\u0026amp; docker run dadrus/heimdall:0.15.0 --version heimdall version v0.15.0 latest - will pull the most recent tagged release.\n$ docker pull dadrus/heimdall:latest \u0026amp;\u0026amp; docker run dadrus/heimdall:latest --version heimdall version 0.15.0 Helm Chart Heimdall can be installed via a Helm chart with a few simple steps, depending on if you are deploying for the first time, or upgrading from an existing installation.\nPrerequisites A Kubernetes version \u0026gt;= 1.27\nHelm 3.0+\nAdding the Helm Repository The heimdall Helm Chart is published at https://dadrus.github.io/heimdall/charts. You can add this repo with the following command:\n$ helm repo add dadrus https://dadrus.github.io/heimdall/charts $ helm repo update Installing the Chart This chart expects a heimdall configuration file with authentication, authorization and so on mechanisms, required for your particular setup, which can be passed by using the -f heimdall.yaml flag during the installation.\nIf you need to override the name of the heimdall resources such as the deployment or services, the traditional nameOverride and fullnameOverride properties are supported.\nBy default, heimdall requires custom resource definitions (CRDs) installed in the cluster. The Helm client will install it for you.\nTo install the chart with the release name my-release (my-release is the name that you choose) and configure heimdall to operate in decision mode:\n$ helm install my-release -f heimdall.yaml dadrus/heimdall If you need proxy mode, install it with:\n$ helm install my-release -f heimdall.yaml --set operationMode=proxy dadrus/heimdall For more advanced configuration and details about helm values, please see the helm chart.\nPost-Install Steps Integration with Ingress After having installed heimdall, you have to integrate it with your ingress controller. For decision mode that means setting corresponding annotations on Ingress resources to let the traffic first be verified by heimdall before it is forwarded to the upstream services by the Ingress Controller.\nMetrics Collection Since heimdall is able to exposes a comprehensive set of Prometheus style metrics (See Metrics for details), you can, assuming you are running a Prometheus Operator in your cluster, create the following PodMonitor resource to enable metrics collection.\napiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: name: heimdall-pod-monitor labels: release: prometheus app.kubernetes.io/instance: my-release app.kubernetes.io/name: heimdall app.kubernetes.io/part-of: heimdall spec: selector: matchLabels: app.kubernetes.io/instance: my-release app.kubernetes.io/name: heimdall podMetricsEndpoints: - path: /metrics port: http-metrics scheme: http interval: 30s jobLabel: heimdall-pod-monitor namespaceSelector: matchNames: - default The definition of the PodMonitor above assumes, you’ve installed heimdall in the default namespace as shown in the Installing the Chart section. If this is not the case, you need to adjust the metadata property by adding the corresponding namespace information, as well as the namespaceSelector.\nIf your Prometheus deployment is not done through the operator, you don’t need to do anything, as the chart already sets the relevant annotations: prometheus.io/scrape, prometheus.io/path and prometheus.io/port.\n","description":"Heimdall is shipped in multiple formats and architectures to suit a variety of deployment patterns. The following chapters describe the available installation options.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_source_code\"\u003eSource Code\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can always build a copy of heimdall by following the following instructions for your OS/environment.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_prerequisites\"\u003ePrerequisites\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://git-scm.com/\"\u003egit\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ca href=\"https://go.dev/dl/\"\u003eGo\u003c/a\u003e programming language \u0026gt;= 1.24\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_download\"\u003eDownload\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRetrieve the latest copy of heimdall source code by cloning the git repository\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003egit clone git@github.com:dadrus/heimdall.git\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_build_with_go\"\u003eBuild with go\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBuild using a single line with \u003ccode\u003ego build\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ CGO_ENABLED\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e0 go build \u003cspan class=\"nt\"\u003e-trimpath\u003c/span\u003e \u003cspan class=\"nt\"\u003e-ldflags\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;-buildid= -w -s -X github.com/dadrus/heimdall/version.Version==my-custom-build\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe flags are set by intention. Using \u003ccode\u003e-trimpath\u003c/code\u003e and \u003ccode\u003e-buildid=\u003c/code\u003e as part of the \u003ccode\u003e-ldflags\u003c/code\u003e argument ensures the build is reproducible (See also \u003ca href=\"https://reproducible-builds.org/\"\u003eReproducible Builds\u003c/a\u003e). Other flags remove unused symbols and debug information.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_binary\"\u003eBinary\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePrebuild binaries are available with every released version on \u003ca href=\"https://github.com/dadrus/heimdall/releases/latest\"\u003eGitHub\u003c/a\u003e, as well as for every merged PR to the main branch. The version of the latter is set to the git SHA1. Supported operating systems/architectures are:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003edarwin/amd64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003edarwin/arm64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elinux/amd64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elinux/arm64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elinux/armv6\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elinux/armv7\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ewindows/amd64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor Linux and Darwin the binaries are archived with tar.gz and for Windows with zip. All archives are signed (see also \u003ca href=\"/docs/operations/security/#_verifying_heimdall_binaries_and_container_images\"\u003eVerifying Heimdall Binaries and Container Images\u003c/a\u003e section on how to verify the signatures).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_download_2\"\u003eDownload\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRetrieve the desired released version of heimdall binary for your operating system/architecture\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eARCH\u003c/span\u003e\u003cspan class=\"o\"\u003e=[\u003c/span\u003eyour \u003cspan class=\"nb\"\u003earch\u003c/span\u003e\u003cspan class=\"o\"\u003e]\u003c/span\u003e\n\u003cspan class=\"nv\"\u003eOS\u003c/span\u003e\u003cspan class=\"o\"\u003e=[\u003c/span\u003eyour os]\n\u003cspan class=\"nv\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"o\"\u003e=[\u003c/span\u003edesired version]\ncurl \u003cspan class=\"nt\"\u003e-L\u003c/span\u003e https://github.com/dadrus/heimdall/releases/download/\u003cspan class=\"k\"\u003e${\u003c/span\u003e\u003cspan class=\"nv\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"k\"\u003e}\u003c/span\u003e/heimdall-\u003cspan class=\"k\"\u003e${\u003c/span\u003e\u003cspan class=\"nv\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"k\"\u003e}\u003c/span\u003e-\u003cspan class=\"k\"\u003e${\u003c/span\u003e\u003cspan class=\"nv\"\u003eOS\u003c/span\u003e\u003cspan class=\"k\"\u003e}\u003c/span\u003e-\u003cspan class=\"k\"\u003e${\u003c/span\u003e\u003cspan class=\"nv\"\u003eARCH\u003c/span\u003e\u003cspan class=\"k\"\u003e}\u003c/span\u003e.tar.gz \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n | \u003cspan class=\"nb\"\u003etar\u003c/span\u003e \u003cspan class=\"nt\"\u003e-z\u003c/span\u003e \u003cspan class=\"nt\"\u003e-x\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_container_image\"\u003eContainer Image\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall utilizes a minimal container multi-arch image which you can find on \u003ca href=\"https://hub.docker.com/r/dadrus/heimdall\"\u003eDockerHub\u003c/a\u003e, or on \u003ca href=\"https://github.com/users/dadrus/packages?repo_name=heimdall\"\u003eGHCR\u003c/a\u003e. As with \u003ca href=\"#_binary\"\u003eBinary\u003c/a\u003e releases, heimdall can be pulled in several flavors. These are however currently limited to the Linux OS. Supported architectures are:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eamd64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003earm64\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003earm/v7\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll container images are rootless - so heimdall will always run as a non-root user within the container. Since Heimdall does not have any dependencies, the images are distroless as well and contain only the binary of heimdall and the settings related to the OS user and group permissions, heimdall is running with.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with the binary distribution, all container images are signed (see also \u003ca href=\"/docs/operations/security/#_verifying_heimdall_binaries_and_container_images\"\u003eVerifying Heimdall Binaries and Container Images\u003c/a\u003e section on how to verify the signatures).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_prerequisites_2\"\u003ePrerequisites\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/install/\"\u003eDocker\u003c/a\u003e, \u003ca href=\"https://podman.io/\"\u003ePodman\u003c/a\u003e, or other container runtime of your choice (examples are however using docker).\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_pull_image\"\u003ePull Image\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe steps below will pull the images from \u003ca href=\"https://hub.docker.com/r/dadrus/heimdall\"\u003eDockerHub\u003c/a\u003e. If you want to pull them from \u003ca href=\"https://github.com/users/dadrus/packages?repo_name=heimdall\"\u003eGHCR\u003c/a\u003e, specify the \u003ccode\u003eghcr.io\u003c/code\u003e registry in front of the repository.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing tag patterns exist:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ex.y.z[-\u0026lt;prerelease-identifier\u0026gt;]\u003c/code\u003e - will pull a specific tagged release.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003edocker pull dadrus/heimdall:0.15.0 \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e docker run dadrus/heimdall:0.15.0 \u003cspan class=\"nt\"\u003e--version\u003c/span\u003e\nheimdall version v0.15.0\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elatest\u003c/code\u003e - will pull the most recent tagged release.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003edocker pull dadrus/heimdall:latest \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e docker run dadrus/heimdall:latest \u003cspan class=\"nt\"\u003e--version\u003c/span\u003e\nheimdall version 0.15.0\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_helm_chart\"\u003eHelm Chart\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall can be installed via a Helm chart with a few simple steps, depending on if you are deploying for the first time, or upgrading from an existing installation.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_prerequisites_3\"\u003ePrerequisites\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eA Kubernetes version \u0026gt;= 1.27\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://helm.sh/docs/intro/install/\"\u003eHelm\u003c/a\u003e 3.0+\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_adding_the_helm_repository\"\u003eAdding the Helm Repository\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe heimdall Helm Chart is published at \u003ccode\u003ehttps://dadrus.github.io/heimdall/charts\u003c/code\u003e. You can add this repo with the following command:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ehelm repo add dadrus https://dadrus.github.io/heimdall/charts\n\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ehelm repo update\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_installing_the_chart\"\u003eInstalling the Chart\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis chart expects a \u003ca href=\"/docs/operations/configuration/#_configuration_file\"\u003eheimdall configuration file\u003c/a\u003e with authentication, authorization and so on mechanisms, required for your particular setup, which can be passed by using the \u003ccode\u003e-f heimdall.yaml\u003c/code\u003e flag during the installation.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you need to override the name of the heimdall resources such as the deployment or services, the traditional \u003ccode\u003enameOverride\u003c/code\u003e and \u003ccode\u003efullnameOverride\u003c/code\u003e properties are supported.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy default, heimdall requires custom resource definitions (CRDs) installed in the cluster. The Helm client will install it for you.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo install the chart with the release name \u003ccode\u003emy-release\u003c/code\u003e (\u003ccode\u003emy-release\u003c/code\u003e is the name that you choose) and configure heimdall to operate in decision mode:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ehelm \u003cspan class=\"nb\"\u003einstall \u003c/span\u003emy-release \u003cspan class=\"nt\"\u003e-f\u003c/span\u003e heimdall.yaml dadrus/heimdall\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you need proxy mode, install it with:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ehelm \u003cspan class=\"nb\"\u003einstall \u003c/span\u003emy-release \u003cspan class=\"nt\"\u003e-f\u003c/span\u003e heimdall.yaml \u003cspan class=\"nt\"\u003e--set\u003c/span\u003e \u003cspan class=\"nv\"\u003eoperationMode\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003eproxy dadrus/heimdall\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor more advanced configuration and details about helm values, \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/charts/heimdall\"\u003eplease see the helm chart\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_post_install_steps\"\u003ePost-Install Steps\u003c/h3\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_integration_with_ingress\"\u003eIntegration with Ingress\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAfter having installed heimdall, you have to integrate it with your ingress controller. For decision mode that means setting corresponding annotations on Ingress resources to let the traffic first be verified by heimdall before it is forwarded to the upstream services by the Ingress Controller.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_metrics_collection\"\u003eMetrics Collection\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince heimdall is able to exposes a comprehensive set of Prometheus style metrics (See \u003ca href=\"/docs/operations/observability/#_metrics\"\u003eMetrics\u003c/a\u003e for details), you can, assuming you are running a \u003ca href=\"https://github.com/prometheus-operator/prometheus-operator\"\u003ePrometheus Operator\u003c/a\u003e in your cluster, create the following \u003ccode\u003ePodMonitor\u003c/code\u003e resource to enable metrics collection.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emonitoring.coreos.com/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ePodMonitor\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-pod-monitor\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003erelease\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eprometheus\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/instance\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-release\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/part-of\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eselector\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematchLabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/instance\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-release\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003epodMetricsEndpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/metrics\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp-metrics\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp\u003c/span\u003e\n \u003cspan class=\"na\"\u003einterval\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e30s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ejobLabel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-pod-monitor\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespaceSelector\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematchNames\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe definition of the \u003ccode\u003ePodMonitor\u003c/code\u003e above assumes, you’ve installed heimdall in the default namespace as shown in the \u003ca href=\"#_installing_the_chart\"\u003eInstalling the Chart\u003c/a\u003e section. If this is not the case, you need to adjust the \u003ccode\u003emetadata\u003c/code\u003e property by adding the corresponding \u003ccode\u003enamespace\u003c/code\u003e information, as well as the \u003ccode\u003enamespaceSelector\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf your Prometheus deployment is not done through the operator, you don’t need to do anything, as the chart already sets the relevant annotations: \u003ccode\u003eprometheus.io/scrape\u003c/code\u003e, \u003ccode\u003eprometheus.io/path\u003c/code\u003e and \u003ccode\u003eprometheus.io/port\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Getting Started"],"tags":null,"title":"Install heimdall","url":"/docs/getting_started/installation/"},{"categories":null,"content":" Overview In this guide, we’ll configure two setups to protect a service that exposes a few endpoints:\nThe /public endpoint is, as the name implies, public. Every request to it should be forwarded as is.\nThe /user endpoint should only be accessible to users with the user role.\nThe /admin endpoint should only be accessible to users with the admin role.\nThe /private endpoint, along with any other potentially exposed endpoints, should not be accessible at all. All requests to it should be rejected.\nFor authentication, we’ll use JWTs containing the respective roles. Authorization will be handled with the help of Open Policy Agent (OPA).\nIn both setups, we’ll create minimal but complete environments using Docker Compose with:\nTraefik as the edge proxy,\ncontainous/whoami (a service that echoes back everything it receives), mimicking our service exposing the endpoints described above,\nan NGINX server serving the public key for verifying the JWTs (mimicking the JWKS endpoint typically exposed by an OIDC provider),\nOPA, which evaluates the authorization policy,\nheimdall, orchestrating everything to enforce the above requirements.\nThis quickstart and others demonstrating different integration options are also available on GitHub. Prerequisites To follow this guide, you’ll need the following tools installed locally:\nDocker,\ndocker-compose, and\na text editor of your choice.\nConfigure Heimdall can be configured via environment variables, as well as using a configuration file. For simplicity, we’ll use a configuration file in this guide. Create a file named heimdall-config.yaml with the following contents:\nlog: (1) level: debug tracing: enabled: false metrics: enabled: false serve: (2) decision: trusted_proxies: - 0.0.0.0/0 mechanisms: (3) authenticators: - id: deny_all (4) type: unauthorized - id: anon (5) type: anonymous - id: jwt_auth (6) type: jwt config: jwks_endpoint: http://idp:8080/.well-known/jwks assertions: issuers: - demo_issuer authorizers: - id: opa (7) type: remote config: endpoint: http://opa:8181/v1/data/{{ .Values.policy }} payload: \u0026#34;{}\u0026#34; expressions: - expression: | Payload.result == true finalizers: - id: create_jwt (8) type: jwt config: signer: key_store: path: /etc/heimdall/signer.pem - id: noop (9) type: noop default_rule: (10) execute: - authenticator: deny_all - finalizer: create_jwt providers: file_system: (11) src: /etc/heimdall/rules.yaml watch: true 1 Since heimdall emits logs at the error level by default, and we want to monitor what’s happening, we’ll set the log level to debug. This way, we’ll not only see the results of a particular rule execution (which you would see with the info log level), but also detailed logs of what’s going on inside each rule. Additionally, we disable tracing and metrics collection, which are pulled by default to an OTEL agent, to avoid error messages related to the unavailability of the agent. For more information on available observability options, see the Observability chapter. 2 This configuration instructs heimdall to trust X-Forwarded-* headers from any source. We need this for integration with Traefik, which uses these headers while forwarding requests to heimdall. The IP address used depends on your local Docker configuration. Never use this in production - always restrict trusted IPs instead! Refer to the documentation on the trusted_proxies property and Security Considerations for more details. 3 Here, we define our catalogue of mechanisms to be used in upstream service-specific rules. In this case, we define authenticators, an authorizer, and finalizers. 4 These two lines define the unauthorized authenticator named deny_all, which rejects all requests. 5 These two lines define the anonymous authenticator named anon, which allows any request and creates a subject with the ID set to anonymous. You can find more information about the subject and other objects here. 6 This and the following lines define and configure the jwt authenticator named jwt_auth. With this configuration, it will check if a request contains an Authorization header with a bearer token in JWT format and validate it using key material fetched from the JWKS endpoint. It will reject requests without a valid JWT or create a subject with the sub claim set to the token’s sub value. All other claims will also be added to the subject’s attributes. 7 Here, we define and configure a remote authorizer named opa. Note how we allow for the overriding of particular settings, which will be specified below when we define the rules. 8 The following lines define the jwt finalizer. This configuration will generate a JWT from the subject object with standard claims, setting the sub claim to the subject’s ID. The key material used for signing is pulled from the referenced key store. 9 These two lines conclude the definition of our mechanisms catalogue and define the noop finalizer, which, as the name implies, does nothing. 10 With the mechanisms catalogue in place, we can now define a default rule. This rule will be triggered if no other rule matches the request. It also acts as a base for defining regular (upstream service-specific) rules. This rule defines a secure default authentication \u0026amp; authorization pipeline, which denies any request using the deny_all authenticator. If overridden by a regular rule, it will create a JWT using the jwt finalizer. 11 The last few lines configure the file_system provider, which allows loading regular rules from the file system. The provider is also configured to watch for changes, so you can modify the rules in real time. Create a file named signer.pem with the following content. This file is our key store with a private key, which you’ll see referenced in the configuration above.\n-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy 1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI zlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X XVwR/5tokqFVrFxt/5c1x7VdccF4nNM= -----END EC PRIVATE KEY----- Do not use this for purposes beyond this tutorial! Now, create a rule file named upstream-rules.yaml to implement the authentication and authorization requirements for your service. Copy the following contents into it:\nversion: \u0026#34;1alpha4\u0026#34; rules: - id: demo:public (1) match: routes: - path: /public forward_to: host: upstream:8081 execute: - authenticator: anon - finalizer: noop - id: demo:protected (2) match: routes: - path: /:user path_params: - name: user type: glob value: \u0026#34;{user,admin}\u0026#34; forward_to: host: upstream:8081 execute: - authenticator: jwt_auth - authorizer: opa config: values: policy: demo/can_access payload: | { \u0026#34;input\u0026#34;: { \u0026#34;role\u0026#34;: {{ quote .Subject.Attributes.role }}, \u0026#34;path\u0026#34;: {{ quote .Request.URL.Path }} } } 1 This rule matches the /public endpoint and forwards the request to our upstream service without performing any verification or transformation. 2 This rule matches the /user and /admin endpoints, handling both authentication and authorization steps. Since we don’t define a finalizer in the second rule’s pipeline, the default rule’s finalizer is reused. There is no need for additional rules, as the default rule will block requests to any other endpoints. Now that everything related to heimdall configuration is in place, let’s create a policy that OPA will use. Create a file named policy.rego with the following contents:\npackage demo default can_access = false (1) can_access { split(input.path, \u0026#34;/\u0026#34;)[1] == input.role } (2) Here, we define our policy can_access within the demo package. The policy is straightforward, evaluating to either true or false.\n1 By default, the can_access policy evaluates to false. 2 It evaluates to true only when the last path fragment of the request matches the user’s role. Now, let’s configure NGINX to expose a static endpoint that serves a JWKS document under the .well-known path. This will allow heimdall to verify the JWTs we will use. Create a file named idp.nginx with the following content:\nworker_processes 1; user nginx; pid /var/run/nginx.pid; events { worker_connections 1024; } http { keepalive_timeout 65; server { listen 8080; location /.well-known/jwks { default_type application/json; root /var/www/nginx; try_files /jwks.json =404; } } } In addition, create a file named jwks.json containing the public key needed to verify the tokens we will use.\n{ \u0026#34;keys\u0026#34;: [{ \u0026#34;use\u0026#34;:\u0026#34;sig\u0026#34;, \u0026#34;kty\u0026#34;:\u0026#34;EC\u0026#34;, \u0026#34;kid\u0026#34;:\u0026#34;key-1\u0026#34;, \u0026#34;crv\u0026#34;:\u0026#34;P-256\u0026#34;, \u0026#34;alg\u0026#34;:\u0026#34;ES256\u0026#34;, \u0026#34;x\u0026#34;:\u0026#34;cv6F6SgBSNWMZKdApZXSuPD6QPtvQyMpk-iRfZxT-vo\u0026#34;, \u0026#34;y\u0026#34;:\u0026#34;C1r3OClUvyDgmDQdvxMdB-ucmZ28b8s4uM4Yg-0BZZ4\u0026#34; }] } We will place it in the /var/www/nginx folder, as mentioned earlier, when we set up our environment.\nNow, let’s configure the environment. To run heimdall as a proxy, create or modify a docker-compose.yaml file. Be sure to update it with the correct paths to your heimdall-config.yaml, upstream-rules.yaml, policy.rego, idp.nginx, and jwks.json files created earlier.\nservices: heimdall: (1) image: dadrus/heimdall:dev ports: - \u0026#34;9090:4455\u0026#34; volumes: - ./heimdall-config.yaml:/etc/heimdall/config.yaml:ro - ./upstream-rules.yaml:/etc/heimdall/rules.yaml:ro - ./signer.pem:/etc/heimdall/signer.pem:ro command: serve proxy -c /etc/heimdall/config.yaml --insecure upstream: (2) image: containous/whoami:latest command: - --port=8081 idp: (3) image: nginx:1.25.4 volumes: - ./idp.nginx:/etc/nginx/nginx.conf:ro - ./jwks.json:/var/www/nginx/jwks.json:ro opa: (4) image: openpolicyagent/opa:0.62.1 command: run --server /etc/opa/policies volumes: - ./policy.rego:/etc/opa/policies/policy.rego:ro 1 These lines configure heimdall to use our configuration, key store, and rule file, and to run in proxy operation mode. We’re using the --insecure flag here to simplify our setup, which disables enforcement of some security settings you can learn about more here. 2 Here, we configure the \u0026#34;upstream\u0026#34; service, which, as mentioned earlier, is a simple service that echoes everything it receives. 3 This section configures our NGINX service, which mimics an IDP system and exposes a JWKS endpoint with our key material. 4 These lines configure our OPA instance to use the authorization policy. Alternatively, if you prefer to implement EAA with heimdall, create or modify the following docker-compose-eaa.yaml file. Be sure to update it with the correct paths to the heimdall-config.yaml, upstream-rules.yaml, policy.rego, idp.nginx, and jwks.json files from above.\nservices: proxy: (1) image: traefik:2.11.0 ports: - \u0026#34;9090:9090\u0026#34; command: \u0026gt; --providers.docker=true --providers.docker.exposedbydefault=false --entryPoints.http.address=\u0026#34;:9090\u0026#34; --accesslog --api=true --api.insecure=true volumes: - \u0026#34;/var/run/docker.sock:/var/run/docker.sock:ro\u0026#34; labels: - traefik.enable=true - traefik.http.routers.traefik_http.service=api@internal - traefik.http.routers.traefik_http.entrypoints=http - traefik.http.middlewares.heimdall.forwardauth.address=http://heimdall:4455 (2) - traefik.http.middlewares.heimdall.forwardauth.authResponseHeaders=Authorization heimdall: (3) image: dadrus/heimdall:dev volumes: - ./heimdall-config.yaml:/etc/heimdall/config.yaml:ro - ./upstream-rules.yaml:/etc/heimdall/rules.yaml:ro - ./signer.pem:/etc/heimdall/signer.pem:ro command: serve decision -c /etc/heimdall/config.yaml --insecure upstream: (4) image: containous/whoami:latest command: - --port=8081 labels: - traefik.enable=true - traefik.http.services.whoami.loadbalancer.server.port=8081 - traefik.http.routers.whoami.rule=PathPrefix(\u0026#34;/\u0026#34;) - traefik.http.routers.whoami.middlewares=heimdall idp: (5) image: nginx:1.25.4 volumes: - ./idp.nginx:/etc/nginx/nginx.conf:ro - ./jwks.json:/var/www/nginx/jwks.json:ro opa: (6) image: openpolicyagent/opa:0.62.1 command: run --server /etc/opa/policies volumes: - ./policy.rego:/etc/opa/policies/policy.rego:ro 1 These lines configure Traefik, which is responsible for dispatching incoming requests and forwarding them to heimdall before routing to the target service. We use the ForwardAuth middleware here, which requires additional configuration at the route level. 2 Here we configure Traefik to forward requests to heimdall. 3 These lines configure heimdall to use our configuration, key store, and rule file, and to run in decision operation mode. We’re using the --insecure flag here to simplify our setup, which disables enforcement of some security settings you can learn about more here. 4 Here, we configure the \u0026#34;upstream\u0026#34; service. As previously mentioned, it is a very simple service that just echoes back everything it receives. We also need to provide some route-level configuration here to ensure requests are forwarded to heimdall. While we could have used a global configuration, we decided against it to avoid adding another configuration file. 5 This is our NGINX service, which mimics an IDP system and exposes a JWKS endpoint with our key material. 6 These lines configure our OPA instance to use the authorization policy. Start Environment Open your terminal and start the services in the directory where the docker-compose.yaml file is located:\n$ docker compose up Consume the API Roll up your sleeves. We’re going to play with our setup now. Open a new terminal window and put it nearby the terminal, you started the environment in. This way you’ll see what is going on in the environment when you use it.\nLet’s try the /public endpoint first.\n$ curl 127.0.0.1:9090/public + You should see an output similar to the one shown below:\n+\nHostname: 94e60bba8498 IP: 127.0.0.1 IP: 172.19.0.3 RemoteAddr: 172.19.0.4:53980 GET /public HTTP/1.1 Host: upstream:8081 User-Agent: curl/8.2.1 Accept: */* Accept-Encoding: gzip Forwarded: for=172.19.0.1;host=127.0.0.1:9090;proto=http + That was expected, as we sent a request to our public endpoint.\nNow, let’s try some other endpoints:\n$ curl -v 127.0.0.1:9090/admin + The -v flag is added to the curl command intentionally. Without it, we won’t see the detailed output. With it, you’ll see the response shown below:\n+\n* processing: 127.0.0.1:9090/admin * Trying 127.0.0.1:9090... * Connected to 127.0.0.1 (127.0.0.1) port 9090 \u0026gt; GET /admin HTTP/1.1 \u0026gt; Host: 127.0.0.1:9090 \u0026gt; User-Agent: curl/8.2.1 \u0026gt; Accept: */* \u0026gt; \u0026lt; HTTP/1.1 401 Unauthorized \u0026lt; Date: Wed, 06 Mar 2024 16:14:05 GMT \u0026lt; Content-Length: 0 \u0026lt; * Connection #0 to host 127.0.0.1 left intact + That is, unauthorized. Requests to any endpoint other than /public will result in the same output.\nLet’s now use a valid JWT to access either the /admin or /user endpoint. Here’s a new request to our /admin endpoint, which includes a bearer token in the Authorization header. This should grant us access:\n$ curl -H \u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjUxMDA3NTEsImlhdCI6MTcwOTc0MDc1MSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI0NjExZDM5Yy00MzI1LTRhMWYtYjdkOC1iMmYxMTE3NDEyYzAiLCJuYmYiOjE3MDk3NDA3NTEsInJvbGUiOiJhZG1pbiIsInN1YiI6IjEifQ.mZZ_UqC8RVzEKBPZbPs4eP-MkXLK22Q27ZJ34UwJiioFdaYXqYJ4ZsatP0TbpKeNyF83mkrrCGL_pWLFTho7Gg\u0026#34; 127.0.0.1:9090/admin + Now we can access the endpoint and see the following output:\n+\nHostname: 94e60bba8498 IP: 127.0.0.1 IP: 172.19.0.2 RemoteAddr: 172.19.0.4:43688 GET /admin HTTP/1.1 Host: upstream:8081 User-Agent: curl/8.2.1 Accept: */* Accept-Encoding: gzip Authorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2MzYwMDAsImlhdCI6MTcxODYzNTcwMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiIyZjc0MjRmNy05ZWFkLTQ4MzItYmM2Yy0xM2FiNDY5NTNjOTQiLCJuYmYiOjE3MTg2MzU3MDAsInN1YiI6IjEifQ._xy_TRsQpiBPsdGi6gh1IOlyep62YpgxiqquXhg-guVdhpslS4PfVH139dv50GOX0fj3F31q8__8QWWvzPJCEI0aEaaMazIVZ24qjyFM2LJvX0o0ILePxfeDU3bhzN8i Forwarded: for=172.19.0.1;host=127.0.0.1:9090;proto=http + Take a closer look at the JWT echoed by our service, e.g. by making use of jwt.io. This token has been issued by heimdall, not the one you sent with curl.\nNow, try the same request to the /user endpoint. It will be refused due to the wrong role. Let’s use a different JWT that should grant us access.\n$ curl -H \u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjUxMDA3NTEsImlhdCI6MTcwOTc0MDc1MSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiIzZmFmNDkxOS0wZjUwLTQ3NGItOGExMy0yOTYzMjEzNThlOTMiLCJuYmYiOjE3MDk3NDA3NTEsInJvbGUiOiJ1c2VyIiwic3ViIjoiMiJ9.W5xCpwsFShS0RpOtrm9vrV2dN6K8pRr5gQnt0kluzLE6oNWFzf7Oot-0YLCPa64Z3XPd7cfGcBiSjrzKZSAj4g\u0026#34; 127.0.0.1:9090/user + This should work now. We omitted the output for brevity, but you should see a successful response.\nTry sending requests to the /private endpoint using any of the tokens from above. It will fail, as heimdall will not allow access.\nCleanup Once you’re done, stop the environment with CTRL-C and delete the created files. If you started Docker Compose in the background, tear down the environment with:\n$ docker compose down ","description":"This simple quickstart guide will walk you through the steps to protect an application using heimdall. You'll learn how to configure heimdall as an authentication and authorization proxy in front of your application, as well as how to implement an Edge-level Authorization Architecture (EAA) with heimdall's help.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_overview\"\u003eOverview\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this guide, we’ll configure two setups to protect a service that exposes a few endpoints:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ccode\u003e/public\u003c/code\u003e endpoint is, as the name implies, public. Every request to it should be forwarded as is.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ccode\u003e/user\u003c/code\u003e endpoint should only be accessible to users with the \u003ccode\u003euser\u003c/code\u003e role.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ccode\u003e/admin\u003c/code\u003e endpoint should only be accessible to users with the \u003ccode\u003eadmin\u003c/code\u003e role.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ccode\u003e/private\u003c/code\u003e endpoint, along with any other potentially exposed endpoints, should not be accessible at all. All requests to it should be rejected.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor authentication, we’ll use JWTs containing the respective roles. Authorization will be handled with the help of Open Policy Agent (OPA).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both setups, we’ll create minimal but complete environments using Docker Compose with:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://doc.traefik.io/traefik/\"\u003eTraefik\u003c/a\u003e as the edge proxy,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://hub.docker.com/r/containous/whoami/\"\u003econtainous/whoami\u003c/a\u003e (a service that echoes back everything it receives), mimicking our service exposing the endpoints described above,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ean \u003ca href=\"https://nginx.org/en/\"\u003eNGINX\u003c/a\u003e server serving the public key for verifying the JWTs (mimicking the JWKS endpoint typically exposed by an OIDC provider),\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://www.openpolicyagent.org/\"\u003eOPA\u003c/a\u003e, which evaluates the authorization policy,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eheimdall, orchestrating everything to enforce the above requirements.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis quickstart and others demonstrating different integration options are also available on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples/docker-compose/quickstarts\"\u003eGitHub\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo follow this guide, you’ll need the following tools installed locally:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/install/\"\u003eDocker\u003c/a\u003e,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/compose/install/\"\u003edocker-compose\u003c/a\u003e, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea text editor of your choice.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configure\"\u003eConfigure\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eHeimdall can be configured via environment variables, as well as using a configuration file. For simplicity, we’ll use a configuration file in this guide. Create a file named \u003ccode\u003eheimdall-config.yaml\u003c/code\u003e with the following contents:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edebug\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emetrics\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eserve\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003edecision\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etrusted_proxies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e0.0.0.0/0\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eunauthorized\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_auth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ejwks_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://idp:8080/.well-known/jwks\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003edemo_issuer\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopa\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://opa:8181/v1/data/{{ .Values.policy }}\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e{}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.result == true\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/signer.pem\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e \u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e(9)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003edefault_rule\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e(10)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eproviders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e(11)\u003c/b\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/rules.yaml\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSince heimdall emits logs at the \u003ccode\u003eerror\u003c/code\u003e level by default, and we want to monitor what’s happening, we’ll set the log level to \u003ccode\u003edebug\u003c/code\u003e. This way, we’ll not only see the results of a particular rule execution (which you would see with the \u003ccode\u003einfo\u003c/code\u003e log level), but also detailed logs of what’s going on inside each rule. Additionally, we disable tracing and metrics collection, which are pulled by default to an OTEL agent, to avoid error messages related to the unavailability of the agent. For more information on available observability options, see the \u003ca href=\"/docs/operations/observability/#_logging\"\u003eObservability\u003c/a\u003e chapter.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis configuration instructs heimdall to trust \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers from any source. We need this for integration with Traefik, which uses these headers while forwarding requests to heimdall. The IP address used depends on your local Docker configuration.\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nNever use this in production - always restrict trusted IPs instead! Refer to the documentation on the \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003etrusted_proxies\u003c/a\u003e property and \u003ca href=\"/docs/operations/security/#_http_header_security_considerations\"\u003eSecurity Considerations\u003c/a\u003e for more details.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we define our \u003ca href=\"/docs/mechanisms/catalogue/\"\u003ecatalogue of mechanisms\u003c/a\u003e to be used in \u003ca href=\"/docs/rules/regular_rule/\"\u003eupstream service-specific rules\u003c/a\u003e. In this case, we define authenticators, an authorizer, and finalizers.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese two lines define the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authenticators/#_unauthorized\"\u003eunauthorized\u003c/a\u003e\u003c/code\u003e authenticator named \u003ccode\u003edeny_all\u003c/code\u003e, which rejects all requests.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese two lines define the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authenticators/#_anonymous\"\u003eanonymous\u003c/a\u003e\u003c/code\u003e authenticator named \u003ccode\u003eanon\u003c/code\u003e, which allows any request and creates a subject with the ID set to \u003ccode\u003eanonymous\u003c/code\u003e. You can find more information about the subject and other objects \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003ehere\u003c/a\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis and the following lines define and configure the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authenticators/#_jwt\"\u003ejwt\u003c/a\u003e\u003c/code\u003e authenticator named \u003ccode\u003ejwt_auth\u003c/code\u003e. With this configuration, it will check if a request contains an \u003ccode\u003eAuthorization\u003c/code\u003e header with a bearer token in JWT format and validate it using key material fetched from the JWKS endpoint. It will reject requests without a valid JWT or create a subject with the \u003ccode\u003esub\u003c/code\u003e claim set to the token’s \u003ccode\u003esub\u003c/code\u003e value. All other claims will also be added to the subject’s attributes.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we define and configure a \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authorizers/#_remote\"\u003eremote\u003c/a\u003e\u003c/code\u003e authorizer named \u003ccode\u003eopa\u003c/code\u003e. Note how we allow for the overriding of particular settings, which will be specified below when we define the rules.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe following lines define the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/finalizers/#_jwt\"\u003ejwt\u003c/a\u003e\u003c/code\u003e finalizer. This configuration will generate a JWT from the subject object with standard claims, setting the \u003ccode\u003esub\u003c/code\u003e claim to the subject’s ID. The key material used for signing is pulled from the referenced key store.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e9\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese two lines conclude the definition of our mechanisms catalogue and define the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/finalizers/#_noop\"\u003enoop\u003c/a\u003e\u003c/code\u003e finalizer, which, as the name implies, does nothing.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e10\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWith the mechanisms catalogue in place, we can now define a \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e. This rule will be triggered if no other rule matches the request. It also acts as a \u003ca href=\"/docs/concepts/rules/#_default_rule_inheritance\"\u003ebase\u003c/a\u003e for defining regular (upstream service-specific) rules. This rule defines a secure default \u003ca href=\"/docs/concepts/pipelines/#_authentication_authorization_pipeline\"\u003eauthentication \u0026amp; authorization pipeline\u003c/a\u003e, which denies any request using the \u003ccode\u003edeny_all\u003c/code\u003e authenticator. If overridden by a regular rule, it will create a JWT using the \u003ccode\u003ejwt\u003c/code\u003e finalizer.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e11\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe last few lines configure the \u003ca href=\"/docs/rules/providers/#_filesystem\"\u003e\u003ccode\u003efile_system\u003c/code\u003e\u003c/a\u003e provider, which allows loading regular rules from the file system. The provider is also configured to watch for changes, so you can modify the rules in real time.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a file named \u003ccode\u003esigner.pem\u003c/code\u003e with the following content. This file is our key store with a private key, which you’ll see referenced in the configuration above.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"s\"\u003e-----BEGIN EC PRIVATE KEY-----\u003c/span\u003e\n\u003cspan class=\"s\"\u003eMIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy\u003c/span\u003e\n\u003cspan class=\"s\"\u003e1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI\u003c/span\u003e\n\u003cspan class=\"s\"\u003ezlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X\u003c/span\u003e\n\u003cspan class=\"s\"\u003eXVwR/5tokqFVrFxt/5c1x7VdccF4nNM=\u003c/span\u003e\n\u003cspan class=\"s\"\u003e-----END EC PRIVATE KEY-----\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nDo not use this for purposes beyond this tutorial!\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNow, create a rule file named \u003ccode\u003eupstream-rules.yaml\u003c/code\u003e to implement the authentication and authorization requirements for your service. Copy the following contents into it:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo:public\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/public\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\n\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo:protected\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/:user\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath_params\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003euser\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eglob\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e{user,admin}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_auth\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopa\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epolicy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo/can_access\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;input\u0026#34;: {\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;role\u0026#34;: {{ quote .Subject.Attributes.role }},\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;path\u0026#34;: {{ quote .Request.URL.Path }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis rule matches the \u003ccode\u003e/public\u003c/code\u003e endpoint and forwards the request to our upstream service without performing any verification or transformation.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis rule matches the \u003ccode\u003e/user\u003c/code\u003e and \u003ccode\u003e/admin\u003c/code\u003e endpoints, handling both authentication and authorization steps.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nSince we don’t define a finalizer in the second rule’s pipeline, the default rule’s finalizer is reused. There is no need for additional rules, as the default rule will block requests to any other endpoints.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNow that everything related to heimdall configuration is in place, let’s create a policy that OPA will use. Create a file named \u003ccode\u003epolicy.rego\u003c/code\u003e with the following contents:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"rego\"\u003e\u003cspan class=\"ow\"\u003epackage\u003c/span\u003e \u003cspan class=\"n\"\u003edemo\u003c/span\u003e\n\n\u003cspan class=\"ow\"\u003edefault\u003c/span\u003e \u003cspan class=\"n\"\u003ecan_access\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n\n\u003cspan class=\"n\"\u003ecan_access\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"n\"\u003esplit\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003epath\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)[\u003c/span\u003e\u003cspan class=\"m\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003erole\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, we define our policy \u003ccode\u003ecan_access\u003c/code\u003e within the \u003ccode\u003edemo\u003c/code\u003e package. The policy is straightforward, evaluating to either true or false.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eBy default, the \u003ccode\u003ecan_access\u003c/code\u003e policy evaluates to false.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eIt evaluates to true only when the last path fragment of the request matches the user’s role.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNow, let’s configure NGINX to expose a static endpoint that serves a JWKS document under the \u003ccode\u003e.well-known\u003c/code\u003e path. This will allow heimdall to verify the JWTs we will use. Create a file named \u003ccode\u003eidp.nginx\u003c/code\u003e with the following content:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eworker_processes 1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\nuser nginx\u003cspan class=\"p\"\u003e;\u003c/span\u003e\npid /var/run/nginx.pid\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\nevents \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n worker_connections 1024\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\nhttp \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n keepalive_timeout 65\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n server \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n listen 8080\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n location /.well-known/jwks \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n default_type application/json\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n root /var/www/nginx\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n try_files /jwks.json \u003cspan class=\"o\"\u003e=\u003c/span\u003e404\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition, create a file named \u003ccode\u003ejwks.json\u003c/code\u003e containing the public key needed to verify the tokens we will use.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;keys\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;use\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;sig\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;kty\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;EC\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;kid\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;key-1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;crv\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;P-256\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;alg\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;ES256\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;x\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;cv6F6SgBSNWMZKdApZXSuPD6QPtvQyMpk-iRfZxT-vo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;y\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;C1r3OClUvyDgmDQdvxMdB-ucmZ28b8s4uM4Yg-0BZZ4\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWe will place it in the \u003ccode\u003e/var/www/nginx\u003c/code\u003e folder, as mentioned earlier, when we set up our environment.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNow, let’s configure the environment. To run \u003cstrong\u003eheimdall as a proxy\u003c/strong\u003e, create or modify a \u003ccode\u003edocker-compose.yaml\u003c/code\u003e file. Be sure to update it with the correct paths to your \u003ccode\u003eheimdall-config.yaml\u003c/code\u003e, \u003ccode\u003eupstream-rules.yaml\u003c/code\u003e, \u003ccode\u003epolicy.rego\u003c/code\u003e, \u003ccode\u003eidp.nginx\u003c/code\u003e, and \u003ccode\u003ejwks.json\u003c/code\u003e files created earlier.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edadrus/heimdall:dev\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e9090:4455\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./heimdall-config.yaml:/etc/heimdall/config.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./upstream-rules.yaml:/etc/heimdall/rules.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./signer.pem:/etc/heimdall/signer.pem:ro\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eserve proxy -c /etc/heimdall/config.yaml --insecure\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eupstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003econtainous/whoami:latest\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e--port=8081\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eidp\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enginx:1.25.4\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./idp.nginx:/etc/nginx/nginx.conf:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./jwks.json:/var/www/nginx/jwks.json:ro\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eopa\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenpolicyagent/opa:0.62.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erun --server /etc/opa/policies\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./policy.rego:/etc/opa/policies/policy.rego:ro\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure heimdall to use our configuration, key store, and rule file, and to run in proxy operation mode.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWe’re using the \u003ccode\u003e--insecure\u003c/code\u003e flag here to simplify our setup, which disables enforcement of some security settings you can learn about more \u003ca href=\"/docs/operations/security/#_defaults\"\u003ehere\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we configure the \u0026#34;upstream\u0026#34; service, which, as mentioned earlier, is a simple service that echoes everything it receives.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis section configures our NGINX service, which mimics an IDP system and exposes a JWKS endpoint with our key material.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure our OPA instance to use the authorization policy.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAlternatively, if you prefer to implement \u003cstrong\u003eEAA with heimdall\u003c/strong\u003e, create or modify the following \u003ccode\u003edocker-compose-eaa.yaml\u003c/code\u003e file. Be sure to update it with the correct paths to the \u003ccode\u003eheimdall-config.yaml\u003c/code\u003e, \u003ccode\u003eupstream-rules.yaml\u003c/code\u003e, \u003ccode\u003epolicy.rego\u003c/code\u003e, \u003ccode\u003eidp.nginx\u003c/code\u003e, and \u003ccode\u003ejwks.json\u003c/code\u003e files from above.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eproxy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik:2.11.0\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e9090:9090\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--providers.docker=true\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--providers.docker.exposedbydefault=false\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--entryPoints.http.address=\u0026#34;:9090\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--accesslog --api=true --api.insecure=true\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e/var/run/docker.sock:/var/run/docker.sock:ro\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.enable=true\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.routers.traefik_http.service=api@internal\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.routers.traefik_http.entrypoints=http\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.middlewares.heimdall.forwardauth.address=http://heimdall:4455\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.middlewares.heimdall.forwardauth.authResponseHeaders=Authorization\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edadrus/heimdall:dev\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./heimdall-config.yaml:/etc/heimdall/config.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./upstream-rules.yaml:/etc/heimdall/rules.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./signer.pem:/etc/heimdall/signer.pem:ro\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eserve decision -c /etc/heimdall/config.yaml --insecure\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eupstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003econtainous/whoami:latest\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e--port=8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.enable=true\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.services.whoami.loadbalancer.server.port=8081\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.routers.whoami.rule=PathPrefix(\u0026#34;/\u0026#34;)\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.routers.whoami.middlewares=heimdall\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eidp\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enginx:1.25.4\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./idp.nginx:/etc/nginx/nginx.conf:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./jwks.json:/var/www/nginx/jwks.json:ro\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eopa\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenpolicyagent/opa:0.62.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erun --server /etc/opa/policies\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./policy.rego:/etc/opa/policies/policy.rego:ro\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure Traefik, which is responsible for dispatching incoming requests and forwarding them to heimdall before routing to the target service. We use the ForwardAuth middleware here, which requires additional configuration at the route level.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we configure Traefik to forward requests to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure heimdall to use our configuration, key store, and rule file, and to run in decision operation mode.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWe’re using the \u003ccode\u003e--insecure\u003c/code\u003e flag here to simplify our setup, which disables enforcement of some security settings you can learn about more \u003ca href=\"/docs/operations/security/#_defaults\"\u003ehere\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we configure the \u0026#34;upstream\u0026#34; service. As previously mentioned, it is a very simple service that just echoes back everything it receives. We also need to provide some route-level configuration here to ensure requests are forwarded to heimdall. While we could have used a global configuration, we decided against it to avoid adding another configuration file.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is our NGINX service, which mimics an IDP system and exposes a JWKS endpoint with our key material.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure our OPA instance to use the authorization policy.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_start_environment\"\u003eStart Environment\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOpen your terminal and start the services in the directory where the \u003ccode\u003edocker-compose.yaml\u003c/code\u003e file is located:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003edocker compose up\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_consume_the_api\"\u003eConsume the API\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRoll up your sleeves. We’re going to play with our setup now. Open a new terminal window and put it nearby the terminal, you started the environment in. This way you’ll see what is going on in the environment when you use it.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eLet’s try the \u003ccode\u003e/public\u003c/code\u003e endpoint first.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl 127.0.0.1:9090/public\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nYou should see an output similar to the one shown below:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eHostname: 94e60bba8498\nIP: 127.0.0.1\nIP: 172.19.0.3\nRemoteAddr: 172.19.0.4:53980\nGET /public HTTP/1.1\nHost: upstream:8081\nUser-Agent: curl/8.2.1\nAccept: \u003cspan class=\"k\"\u003e*\u003c/span\u003e/\u003cspan class=\"k\"\u003e*\u003c/span\u003e\nAccept-Encoding: \u003cspan class=\"nb\"\u003egzip\n\u003c/span\u003eForwarded: \u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e172.19.0.1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003ehost\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e127.0.0.1:9090\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003eproto\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttp\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nThat was expected, as we sent a request to our public endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eNow, let’s try some other endpoints:\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl \u003cspan class=\"nt\"\u003e-v\u003c/span\u003e 127.0.0.1:9090/admin\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nThe \u003ccode\u003e-v\u003c/code\u003e flag is added to the curl command intentionally. Without it, we won’t see the detailed output. With it, you’ll see the response shown below:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"k\"\u003e*\u003c/span\u003e processing: 127.0.0.1:9090/admin\n\u003cspan class=\"k\"\u003e*\u003c/span\u003e Trying 127.0.0.1:9090...\n\u003cspan class=\"k\"\u003e*\u003c/span\u003e Connected to 127.0.0.1 \u003cspan class=\"o\"\u003e(\u003c/span\u003e127.0.0.1\u003cspan class=\"o\"\u003e)\u003c/span\u003e port 9090\n\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e GET /admin HTTP/1.1\n\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e Host: 127.0.0.1:9090\n\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e User-Agent: curl/8.2.1\n\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e Accept: \u003cspan class=\"k\"\u003e*\u003c/span\u003e/\u003cspan class=\"k\"\u003e*\u003c/span\u003e\n\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e\n\u0026lt; HTTP/1.1 401 Unauthorized\n\u0026lt; Date: Wed, 06 Mar 2024 16:14:05 GMT\n\u0026lt; Content-Length: 0\n\u0026lt;\n\u003cspan class=\"k\"\u003e*\u003c/span\u003e Connection \u003cspan class=\"c\"\u003e#0 to host 127.0.0.1 left intact\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nThat is, unauthorized. Requests to any endpoint other than \u003ccode\u003e/public\u003c/code\u003e will result in the same output.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eLet’s now use a valid JWT to access either the \u003ccode\u003e/admin\u003c/code\u003e or \u003ccode\u003e/user\u003c/code\u003e endpoint. Here’s a new request to our \u003ccode\u003e/admin\u003c/code\u003e endpoint, which includes a bearer token in the \u003ccode\u003eAuthorization\u003c/code\u003e header. This should grant us access:\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjUxMDA3NTEsImlhdCI6MTcwOTc0MDc1MSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI0NjExZDM5Yy00MzI1LTRhMWYtYjdkOC1iMmYxMTE3NDEyYzAiLCJuYmYiOjE3MDk3NDA3NTEsInJvbGUiOiJhZG1pbiIsInN1YiI6IjEifQ.mZZ_UqC8RVzEKBPZbPs4eP-MkXLK22Q27ZJ34UwJiioFdaYXqYJ4ZsatP0TbpKeNyF83mkrrCGL_pWLFTho7Gg\u0026#34;\u003c/span\u003e 127.0.0.1:9090/admin\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nNow we can access the endpoint and see the following output:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eHostname: 94e60bba8498\nIP: 127.0.0.1\nIP: 172.19.0.2\nRemoteAddr: 172.19.0.4:43688\nGET /admin HTTP/1.1\nHost: upstream:8081\nUser-Agent: curl/8.2.1\nAccept: \u003cspan class=\"k\"\u003e*\u003c/span\u003e/\u003cspan class=\"k\"\u003e*\u003c/span\u003e\nAccept-Encoding: \u003cspan class=\"nb\"\u003egzip\n\u003c/span\u003eAuthorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2MzYwMDAsImlhdCI6MTcxODYzNTcwMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiIyZjc0MjRmNy05ZWFkLTQ4MzItYmM2Yy0xM2FiNDY5NTNjOTQiLCJuYmYiOjE3MTg2MzU3MDAsInN1YiI6IjEifQ._xy_TRsQpiBPsdGi6gh1IOlyep62YpgxiqquXhg-guVdhpslS4PfVH139dv50GOX0fj3F31q8__8QWWvzPJCEI0aEaaMazIVZ24qjyFM2LJvX0o0ILePxfeDU3bhzN8i\nForwarded: \u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e172.19.0.1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003ehost\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e127.0.0.1:9090\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003eproto\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttp\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nTake a closer look at the JWT echoed by our service, e.g. by making use of \u003ca href=\"https://jwt.io\"\u003ejwt.io\u003c/a\u003e. This token has been issued by heimdall, not the one you sent with curl.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eNow, try the same request to the \u003ccode\u003e/user\u003c/code\u003e endpoint. It will be refused due to the wrong role. Let’s use a different JWT that should grant us access.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjUxMDA3NTEsImlhdCI6MTcwOTc0MDc1MSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiIzZmFmNDkxOS0wZjUwLTQ3NGItOGExMy0yOTYzMjEzNThlOTMiLCJuYmYiOjE3MDk3NDA3NTEsInJvbGUiOiJ1c2VyIiwic3ViIjoiMiJ9.W5xCpwsFShS0RpOtrm9vrV2dN6K8pRr5gQnt0kluzLE6oNWFzf7Oot-0YLCPa64Z3XPd7cfGcBiSjrzKZSAj4g\u0026#34;\u003c/span\u003e 127.0.0.1:9090/user\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e+\nThis should work now. We omitted the output for brevity, but you should see a successful response.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eTry sending requests to the \u003ccode\u003e/private\u003c/code\u003e endpoint using any of the tokens from above. It will fail, as heimdall will not allow access.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cleanup\"\u003eCleanup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOnce you’re done, stop the environment with \u003ccode\u003eCTRL-C\u003c/code\u003e and delete the created files. If you started Docker Compose in the background, tear down the environment with:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003edocker compose down\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Getting Started"],"tags":null,"title":"Protect an Application","url":"/docs/getting_started/protect_an_app/"},{"categories":null,"content":" Caddy is a modern web server and reverse proxy known for its automatic HTTPS and simplicity. Heimdall can be integrated with Caddy using the forward_auth directive. If heimdall responds with a 2XX status code, Caddy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\nPrerequisites Integration with Caddy requires heimdall being operated in Decision Operation Mode.\nConfiguration Options Since Caddy offers extensive configuration options and heimdall supports multiple integration methods, you can choose any of the examples below. Each setup ensures heimdall can construct the URL of the protected backend server for rule matching purposes.\nIn most cases, you need to configure heimdall to trust your Caddy instances by setting trusted_proxies. Exceptions are detailed in the sections below.\nForward all information in X-Forwarded-* headers This is the simplest integration method, leveraging the X-Forwarded-Method, X-Forwarded-Proto, X-Forwarded-Host, and X-Forwarded-Uri headers that Caddy automatically sets.\nProper configuration of trusted_proxies is mandatory when using this option to prevent spoofing of the X-Forwarded-* headers. # Caddyfile :9090 { reverse_proxy upstream:8081 forward_auth https://heimdall:4455 { (1) uri / (2) copy_headers Authorization (3) } } 1 Configures Caddy to authenticate requests with heimdall before proxying them to the upstream service. Directives before this line are unrelated to heimdall integration and are included for configuration completeness. 2 Specifies heimdall’s verification endpoint. Here, / is used since all relevant request details are passed via X-Forwarded-* headers. 3 Ensures Caddy forwards the Authorization header set by heimdall to the upstream service. This value depends on your Contextualizers and Finalizers configuration) Forward only the path and query information With this method, X-Forwarded-* headers are not used, relying solely on the standard request data. This means the original request’s HTTP scheme and client IP are not available, but there is no need to configure the trusted_proxies property.\n# Caddyfile :9090 { reverse_proxy upstream:8081 forward_auth https://heimdall:4455 { (1) uri {http.request.uri} (2) method {http.request.method} (3) header_down Host {http.request.hostport} (4) copy_headers Authorization (5) } } 1 As in the previous approach, Caddy is configured to authenticate requests with heimdall before proxying them to the upstream service. Directives before this line are unrelated to heimdall integration and are included for configuration completeness. 2 Specifies heimdall’s verification endpoint. Unlike the previous integration method, the uri is set to the original request URI. 3 Ensures Caddy forwards the request using the same HTTP method as the original request. 4 Sets the Host header to match the original request, making it accessible to Heimdall. 5 Ensures Caddy forwards the Authorization header set by heimdall to the upstream service. This value depends on your Contextualizers and Finalizers configuration. Additional Resources Checkout the examples on GitHub for a working demo.\n","description":"This guide explains how to integrate heimdall with Caddy, an open-source web server and reverse proxy known for its automatic HTTPS and simple configuration.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://caddyserver.com\"\u003eCaddy\u003c/a\u003e is a modern web server and reverse proxy known for its automatic HTTPS and simplicity. Heimdall can be integrated with Caddy using the \u003ca href=\"https://caddyserver.com/docs/caddyfile/directives/forward_auth\"\u003eforward_auth\u003c/a\u003e directive. If heimdall responds with a 2XX status code, Caddy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with Caddy requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration_options\"\u003eConfiguration Options\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince Caddy offers extensive configuration options and heimdall supports multiple integration methods, you can choose any of the examples below. Each setup ensures heimdall can construct the URL of the protected backend server for rule matching purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn most cases, you need to configure heimdall to trust your Caddy instances by setting \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003etrusted_proxies\u003c/a\u003e. Exceptions are detailed in the sections below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_forward_all_information_in_x_forwarded_headers\"\u003eForward all information in \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis is the simplest integration method, leveraging the \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e, and \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e headers that Caddy automatically sets.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nProper configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e is mandatory when using this option to prevent spoofing of the \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode\u003e# Caddyfile\n\n:9090 {\n reverse_proxy upstream:8081\n\n forward_auth https://heimdall:4455 { \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n uri / \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n copy_headers Authorization \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n }\n}\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures Caddy to authenticate requests with heimdall before proxying them to the upstream service. Directives before this line are unrelated to heimdall integration and are included for configuration completeness.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSpecifies heimdall’s verification endpoint. Here, \u003ccode\u003e/\u003c/code\u003e is used since all relevant request details are passed via \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eEnsures Caddy forwards the \u003ccode\u003eAuthorization\u003c/code\u003e header set by heimdall to the upstream service. This value depends on your \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration)\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_forward_only_the_path_and_query_information\"\u003eForward only the path and query information\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith this method, \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers are not used, relying solely on the standard request data. This means the original request’s HTTP scheme and client IP are not available, but there is no need to configure the \u003ccode\u003etrusted_proxies\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode\u003e# Caddyfile\n\n:9090 {\n reverse_proxy upstream:8081\n\n forward_auth https://heimdall:4455 { \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n uri {http.request.uri} \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n method {http.request.method} \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n header_down Host {http.request.hostport} \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n copy_headers Authorization \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n }\n}\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAs in the previous approach, Caddy is configured to authenticate requests with heimdall before proxying them to the upstream service. Directives before this line are unrelated to heimdall integration and are included for configuration completeness.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSpecifies heimdall’s verification endpoint. Unlike the previous integration method, the \u003ccode\u003euri\u003c/code\u003e is set to the original request URI.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eEnsures Caddy forwards the request using the same HTTP method as the original request.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSets the \u003ccode\u003eHost\u003c/code\u003e header to match the original request, making it accessible to Heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eEnsures Caddy forwards the \u003ccode\u003eAuthorization\u003c/code\u003e header set by heimdall to the upstream service. This value depends on your \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCheckout the examples on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e for a working demo.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Caddy Integration","url":"/guides/proxies/caddy/"},{"categories":null,"content":" Overview Pipelines are specified in rules and are used to authenticate and authorize the particular requests, as well as to handle encountered errors.\nAs described in the Discover heimdall chapter and also shown in the diagram below, central aspects of heimdall are upstream specific pipelines, which allow you orchestrating different services to authenticate, enrich and authorize incoming HTTP requests, transform the resulting subject information into a format, or obtain credentials required for the communication with the particular upstream services.\nFigure 1. Authentication \u0026amp; Authorization Pipeline Authentication \u0026amp; Authorization Pipeline Even the figure above shows four steps, these are actually organized in three stages as depicted in the diagram below. Each of these stages is assembled by as many mechanisms (which represent the actual steps), as required to fulfill the corresponding requirements.\nFigure 2. Pipeline Stages Authentication Stage: In that stage you can use any amount of authentication mechanisms, to let heimdall communicate with the actual authentication systems. This can be getting information about the authenticated subject of the request, getting key material to verify the authentication information provided in the request, or perform some other activities related to authentication. This stage is mandatory, which means, at least one authentication mechanism must be specified. If multiple are specified, the subsequent ones are only executed if the previous either fail or were not responsible for the authentication data available with the request.\nAuthorization Stage: In that stage you can make use of any amount of contextualization and authorization mechanisms in any order to fulfill your authorization requirements. Here, you let heimdall communicate with other systems to collect contextual information required for authorization purposes (like e.g. getting the country for the IP, the request came from, retrieving subscription status of your customer, etc), and to perform the actual authorization, e.g. by talking to an Open Policy Agent, OpenFGA, any other type of authorization system, or even let heimdall perform the required checks locally. That stage is optional and is only executed after the successful execution of the authentication stage. The mechanisms specified in it are executed in order of their definition.\nFinalization Stage: In that stage, you can use any amount of finalization mechanisms to complete the pipeline execution and allows you transforming the information collected about the subject in the previous stages into a format expected or required by your upstream service, or even driving specific protocols, e.g. to obtain a token required by the upstream service. That stage is optional and is only executed after the successful execution of the previous stage. The mechanisms specified in it are executed in order of their definition.\nStages are implicit. That is, a pipeline is just a list of mechanisms to be executed in the specified order. That means, all authentication mechanisms must be specified before any contextualization, authorization or finalization mechanisms are specified, with all finalization mechanisms required to be specified at the end. Violation of that rule will let heimdall refuse loading of the particular rule. Error Pipeline Obviously, a mechanism used in the previously described Authentication \u0026amp; Authorization Pipeline may fail. That will result in the execution of the error pipeline, which is basically a list of error handler mechanisms, ranging from a simple error response to the client (which sent the request) to sophisticated ones supporting complex logic and redirects. Mechanisms in this pipeline define conditions under which they are executed. The first mechanism, which condition evaluates to true is executed and other are ignored. If conditions of all mechanisms fail, the default error handler is executed (see also below).\nThe error pipeline is optional. If no error handlers are defined, heimdall will just response with an HTTP response code based on the error raised in the authentication \u0026amp; authorization pipeline.\n","description":"Pipelines let you orchestrate existing authentication and authorization systems via mechanisms.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_overview\"\u003eOverview\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePipelines are specified in \u003ca href=\"/docs/concepts/rules/\"\u003erules\u003c/a\u003e and are used to authenticate and authorize the particular requests, as well as to handle encountered errors.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs described in the \u003ca href=\"/docs/getting_started/discover_heimdall/\"\u003eDiscover heimdall\u003c/a\u003e chapter and also shown in the diagram below, central aspects of heimdall are upstream specific pipelines, which allow you orchestrating different services to authenticate, enrich and authorize incoming HTTP requests, transform the resulting subject information into a format, or obtain credentials required for the communication with the particular upstream services.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_fig_heimdall_request_pipeline\" class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-92616c018b7cc4e879c86947d2cf5d7c.svg\" alt=\"Diagram\" width=\"1290\" height=\"294\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 1. Authentication \u0026amp; Authorization Pipeline\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEven the figure above shows four steps, these are actually organized in three stages as depicted in the diagram below. Each of these stages is assembled by as many \u003ca href=\"/docs/concepts/mechanisms/\"\u003emechanisms\u003c/a\u003e (which represent the actual steps), as required to fulfill the corresponding requirements.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-f2a2cc62dbb0fff1aea173b6d0a9aba7.svg\" alt=\"Diagram\" width=\"1340\" height=\"490\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 2. Pipeline Stages\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eAuthentication Stage:\u003c/strong\u003e In that stage you can use any amount of \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eauthentication\u003c/a\u003e mechanisms, to let heimdall communicate with the actual authentication systems. This can be getting information about the authenticated subject of the request, getting key material to verify the authentication information provided in the request, or perform some other activities related to authentication. This stage is mandatory, which means, at least one authentication mechanism must be specified. If multiple are specified, the subsequent ones are only executed if the previous either fail or were not responsible for the authentication data available with the request.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eAuthorization Stage:\u003c/strong\u003e In that stage you can make use of any amount of \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003econtextualization\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/authorizers/\"\u003eauthorization\u003c/a\u003e mechanisms in any order to fulfill your authorization requirements. Here, you let heimdall communicate with other systems to collect contextual information required for authorization purposes (like e.g. getting the country for the IP, the request came from, retrieving subscription status of your customer, etc), and to perform the actual authorization, e.g. by talking to an Open Policy Agent, OpenFGA, any other type of authorization system, or even let heimdall perform the required checks locally. That stage is optional and is only executed after the successful execution of the authentication stage. The mechanisms specified in it are executed in order of their definition.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eFinalization Stage:\u003c/strong\u003e In that stage, you can use any amount of \u003ca href=\"/docs/mechanisms/finalizers/\"\u003efinalization\u003c/a\u003e mechanisms to complete the pipeline execution and allows you transforming the information collected about the subject in the previous stages into a format expected or required by your upstream service, or even driving specific protocols, e.g. to obtain a token required by the upstream service. That stage is optional and is only executed after the successful execution of the previous stage. The mechanisms specified in it are executed in order of their definition.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nStages are implicit. That is, a pipeline is just a list of mechanisms to be executed in the specified order. That means, all \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eauthentication\u003c/a\u003e mechanisms must be specified before any \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003econtextualization\u003c/a\u003e, \u003ca href=\"/docs/mechanisms/authorizers/\"\u003eauthorization\u003c/a\u003e or \u003ca href=\"/docs/mechanisms/finalizers/\"\u003efinalization\u003c/a\u003e mechanisms are specified, with all \u003ca href=\"/docs/mechanisms/finalizers/\"\u003efinalization\u003c/a\u003e mechanisms required to be specified at the end. Violation of that rule will let heimdall refuse loading of the particular rule.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_error_pipeline\"\u003eError Pipeline\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eObviously, a \u003ca href=\"/docs/concepts/mechanisms/\"\u003emechanism\u003c/a\u003e used in the previously described \u003ca href=\"#_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/a\u003e may fail. That will result in the execution of the error pipeline, which is basically a list of \u003ca href=\"/docs/mechanisms/error_handlers/\"\u003eerror handler\u003c/a\u003e mechanisms, ranging from a simple error response to the client (which sent the request) to sophisticated ones supporting complex logic and redirects. Mechanisms in this pipeline define conditions under which they are executed. The first mechanism, which condition evaluates to true is executed and other are ignored. If conditions of all mechanisms fail, the default error handler is executed (see also below).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe error pipeline is optional. If no error handlers are defined, heimdall will just response with an HTTP response code based on the error raised in the authentication \u0026amp; authorization pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Concepts"],"tags":null,"title":"Pipelines","url":"/docs/concepts/pipelines/"},{"categories":null,"content":" Contour is an ingress controller for Kubernetes, implementing a control plane for Envoy edge and a service proxy.\nPrerequisites Integration with Contour requires heimdall being operated in Decision Operation Mode exposing Envoy’s external authorization GRPC protocol.\nBeing security first ingress controller, Contour enforces TLS for communication between Envoy and any external authorization service. For that reason, heimdall must be configured with an appropriate key material and certificate. Same is actually also true for the http route definition of the actual upstream service. The only exception is when configuring Contour using heimdall as a global external auth service.\nGeneral Configuration The official External Authorization Guide from Contour describes the required steps in great detail. While following it, please make attention to the following details specific to heimdall as described below.\nIf you use cert-manager, ensure the feature gate AdditionalCertificateOutputFormats is set to true. This lets cert-manager creating secrets with a property named tls-combined.pem, combining both the key and the certificate in one object, as also typically provided by any other CA and expected by heimdall.\nWhen you configure the Certificate resource to let cert-manager issue a TLS certificate for heimdall, configure the additionalOutputFormats property with the type CombinedPEM to make use of the aforesaid feature gate and have the tls-combined.pem property set in the resulting secret. Here a small snippet showing the relevant parts:\napiVersion: cert-manager.io/v1 kind: Certificate spec: # ... additionalOutputFormats: - type: CombinedPEM # ... If TLS is enabled, which, as said above, is required for integration with Contour, by default heimdall is configured to support TLS v1.3 only. However, it looks like Contour does not configure Envoy to support TLS v1.3 so that the communication with heimdall happens via TLS v1.2 and below. For that reason you have to configure the main service of heimdall to TLS v1.2 being the minimum supported version. Otherwise, Envoy will not be able communicating with heimdall, resulting in 403 responses for any request. The following snippet shows the relevant parts in the heimdall configuration file:\n# ... serve: tls: # important! see explanations above min_version: TLS1.2 key_store: # path to the pem file with key and certificates path: /certs/tls-combined.pem # ... Ensure heimdall is started in Decision Operation Mode exposing Envoy’s external authorization GRPC protocol (achieved by passing the --envoy-grpc flag while starting heimdall) and the required secret with the TLS key material is available to the heimdall container. The following snippet shows the relevant values configuration if you use helm for installing/updating heimdall:\nextraArgs: - --envoy-grpc deployment: volumes: - name: tls-cert-volume secret: secretName: \u0026lt;name of the corresponding secret\u0026gt; volumeMounts: - name: tls-cert-volume readOnly: true mountPath: /certs Define an ExtensionService as described in the referenced Contour guide for heimdall and also shown below\napiVersion: projectcontour.io/v1alpha1 kind: ExtensionService metadata: namespace: \u0026lt;namespace in which heimdall is installed\u0026gt; name: heimdall-ext-service spec: protocol: h2 services: - name: heimdall port: 4455 The ExtensionService resource definition tells Contour to program Envoy with an upstream cluster directing traffic to heimdall. That way, as also described in the Envoy Integration Guide, Envoy will delegate authentication and authorization to heimdall. If heimdall answers with a 200 OK HTTP code, Envoy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is treated as an error and is returned to the client.\nGlobal Configuration A global configuration allows you to setup a single external authorization configuration for all your virtual hosts (HTTP and HTTPS). The only thing you have to do is to reference the ExtensionService, defined above in your Contour config. This is achieved with the following snippet:\nglobalExtAuth: extensionService: \u0026lt;namespace in which heimdall is installed\u0026gt;/\u0026lt;name of the extention service\u0026gt; failOpen: false responseTimeout: 1s You can now define your Ingress Rules. When using HTTPProxy resources instead, Contour allows overriding or disabling of the external auth service on the route level for HTTPs routes.\nRoute-based Configuration The only way to have route based external auth service configuration in Contour, is the usage of HTTPProxy resource instead of the regular Ingress rules, allowing referencing the ExtensionService. Here an example:\napiVersion: projectcontour.io/v1 kind: HTTPProxy metadata: name: echo-app namespace: quickstarts labels: app.kubernetes.io/name: echo-app spec: virtualhost: fqdn: echo-app.local tls: secretName: echo-app authorization: (1) extensionRef: namespace: heimdall name: heimdall-ext-service routes: - conditions: - prefix: / services: - name: echo-app port: 8080 1 Reference to the ExtensionService. Additional Resources Checkout the examples on GitHub for a working demo.\n","description":"This guide explains how to integrate heimdall with Contour, an open source, high performance ingress controller for Kubernetes.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://projectcontour.io/\"\u003eContour\u003c/a\u003e is an ingress controller for Kubernetes, implementing a control plane for \u003ca href=\"https://www.envoyproxy.io/\"\u003eEnvoy\u003c/a\u003e edge and a service proxy.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with Contour requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e exposing Envoy’s external authorization \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto\"\u003eGRPC protocol\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eBeing security first ingress controller, Contour enforces TLS for communication between Envoy and any external authorization service. For that reason, heimdall must be configured with an appropriate key material and certificate. Same is actually also true for the http route definition of the actual upstream service. The only exception is when configuring Contour using heimdall as a global external auth service.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_general_configuration\"\u003eGeneral Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe official \u003ca href=\"https://projectcontour.io/docs/main/guides/external-authorization/\"\u003eExternal Authorization Guide\u003c/a\u003e from Contour describes the required steps in great detail. While following it, please make attention to the following details specific to heimdall as described below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIf you use \u003ca href=\"https://cert-manager.io/\"\u003ecert-manager\u003c/a\u003e, ensure the feature gate \u003ccode\u003eAdditionalCertificateOutputFormats\u003c/code\u003e is set to \u003ccode\u003etrue\u003c/code\u003e. This lets cert-manager creating secrets with a property named \u003ccode\u003etls-combined.pem\u003c/code\u003e, combining both the key and the certificate in one object, as also typically provided by any other CA and expected by heimdall.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWhen you configure the \u003ccode\u003eCertificate\u003c/code\u003e resource to let cert-manager issue a TLS certificate for heimdall, configure the \u003ccode\u003eadditionalOutputFormats\u003c/code\u003e property with the type \u003ccode\u003eCombinedPEM\u003c/code\u003e to make use of the aforesaid feature gate and have the \u003ccode\u003etls-combined.pem\u003c/code\u003e property set in the resulting secret. Here a small snippet showing the relevant parts:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecert-manager.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eCertificate\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# ...\u003c/span\u003e\n \u003cspan class=\"na\"\u003eadditionalOutputFormats\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eCombinedPEM\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# ...\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf TLS is enabled, which, as said above, is required for integration with Contour, by default heimdall is configured to support TLS v1.3 only. However, it looks like Contour does not configure Envoy to support TLS v1.3 so that the communication with heimdall happens via TLS v1.2 and below. For that reason you have to configure the main service of heimdall to TLS v1.2 being the minimum supported version. Otherwise, Envoy will not be able communicating with heimdall, resulting in \u003ccode\u003e403\u003c/code\u003e responses for any request. The following snippet shows the relevant parts in the heimdall configuration file:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# ...\u003c/span\u003e\n\u003cspan class=\"na\"\u003eserve\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# important! see explanations above\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# path to the pem file with key and certificates\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/certs/tls-combined.pem\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# ...\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eEnsure heimdall is started in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e exposing Envoy’s external authorization \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto\"\u003eGRPC protocol\u003c/a\u003e (achieved by passing the \u003ccode\u003e--envoy-grpc\u003c/code\u003e flag while starting heimdall) and the required secret with the TLS key material is available to the heimdall container. The following snippet shows the relevant values configuration if you use helm for installing/updating heimdall:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eextraArgs\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e--envoy-grpc\u003c/span\u003e\n\u003cspan class=\"na\"\u003edeployment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etls-cert-volume\u003c/span\u003e\n \u003cspan class=\"na\"\u003esecret\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esecretName\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;name of the corresponding secret\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumeMounts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etls-cert-volume\u003c/span\u003e\n \u003cspan class=\"na\"\u003ereadOnly\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003emountPath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/certs\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDefine an \u003ca href=\"https://projectcontour.io/docs/1.25/config/api/#projectcontour.io/v1alpha1.ExtensionService\"\u003e\u003ccode\u003eExtensionService\u003c/code\u003e\u003c/a\u003e as described in the referenced Contour guide for heimdall and also shown below\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eprojectcontour.io/v1alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eExtensionService\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;namespace in which heimdall is installed\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-ext-service\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprotocol\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eh2\u003c/span\u003e\n \u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e4455\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ccode\u003eExtensionService\u003c/code\u003e resource definition tells Contour to program Envoy with an upstream cluster directing traffic to heimdall. That way, as also described in the \u003ca href=\"/guides/proxies/envoy/\"\u003eEnvoy Integration Guide\u003c/a\u003e, Envoy will delegate authentication and authorization to heimdall. If heimdall answers with a \u003ccode\u003e200 OK\u003c/code\u003e HTTP code, Envoy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is treated as an error and is returned to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA global configuration allows you to setup a single external authorization configuration for all your virtual hosts (HTTP and HTTPS). The only thing you have to do is to reference the \u003ccode\u003eExtensionService\u003c/code\u003e, defined above in your Contour config. This is achieved with the following snippet:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eglobalExtAuth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eextensionService\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;namespace in which heimdall is installed\u0026gt;/\u0026lt;name of the extention service\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003efailOpen\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"na\"\u003eresponseTimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can now define your \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/ingress/#the-ingress-resource\"\u003eIngress Rules\u003c/a\u003e. When using \u003ca href=\"https://projectcontour.io/docs/1.25/config/api/#projectcontour.io/v1.HTTPProxy\"\u003e\u003ccode\u003eHTTPProxy\u003c/code\u003e\u003c/a\u003e resources instead, Contour allows overriding or disabling of the external auth service on the route level for HTTPs routes.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_route_based_configuration\"\u003eRoute-based Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe only way to have route based external auth service configuration in Contour, is the usage of \u003ca href=\"https://projectcontour.io/docs/1.25/config/api/#projectcontour.io/v1.HTTPProxy\"\u003e\u003ccode\u003eHTTPProxy\u003c/code\u003e\u003c/a\u003e resource instead of the regular Ingress rules, allowing referencing the \u003ccode\u003eExtensionService\u003c/code\u003e. Here an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eprojectcontour.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eHTTPProxy\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eecho-app\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003equickstarts\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapp.kubernetes.io/name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eecho-app\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evirtualhost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efqdn\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eecho-app.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esecretName\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eecho-app\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eextensionRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-ext-service\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econditions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/\u003c/span\u003e\n \u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eecho-app\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e8080\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eReference to the \u003ccode\u003eExtensionService\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCheckout the examples on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e for a working demo.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Contour Integration","url":"/guides/proxies/contour/"},{"categories":null,"content":" Mechanism Categories All supported mechanisms fall into the following five categories, each implementing different mechanisms types (addressing different protocols or scenarios):\nAuthenticators, which inspect HTTP requests for presence of authentication objects, like e.g. the presence of a specific cookie. If such objects exist, authenticators verify the related authentication status and obtain information about the corresponding subject. A subject, could be a user who tries to use particular functionality of the upstream service, a machine (if you have machine-2-machine interaction), or something different. Authenticators ensure the subject is authenticated and the information available about it is valid.\nAuthorizers, which ensure that the subject obtained via an authenticator has the required permissions to submit the given HTTP request and thus to execute the corresponding logic in the upstream service. E.g. a specific endpoint of the upstream service might only be accessible to a \u0026#34;user\u0026#34; from the \u0026#34;admin\u0026#34; group, or to an HTTP request if a specific HTTP header is set.\nContextualizers, which enrich the information about the subject obtained via an authenticator with further contextual information, required either by the upstream service itself or an authorizer. This can be handy if the actual authentication system doesn’t have all information about the subject (which is usually the case in microservice architectures), or if dynamic information about the subject, like the current location based on the IP address, is required.\nFinalizers, which, as the name implies, finalize the execution of the pipeline and enrich the request with data such as subject information or authentication tokens required by the upstream service. The available options range from doing nothing, adding a simple header over a structured JWT, to driving specific protocols, e.g. to obtain a token required by the upstream service.\nError Handlers, which are responsible for execution of logic if any of the mechanisms described above fail. These range from a simple error response to the client, which sent the request, to sophisticated ones, supporting complex logic and redirects.\nAll mechanisms are stateless. Even some of them support caching, the corresponding data is not stored on the mechanisms level. A cache backend is used instead, defaulting to an in-memory key-value store. Mechanisms Catalogue Those mechanisms, which should be available for usage in rules, must be defined/configured first. That suits the following purposes:\nMechanisms are per se generic and must be configured for usage in particular use cases.\nThat configuration provides useful default behavior addressing your particular requirements, like which identity management system to use, etc.\nOnly those mechanisms, which are defined can be used in rules. With other words, if you do not define any mechanism, you cannot define any rule.\nThat makes the definition of rules also very simple - just reference the required mechanisms and \u0026#34;tune\u0026#34; the configuration, specified in the catalogue only if required. Not everything can be tuned though.\nIt also provides secure defaults. E.g. that way you can ensure heimdall communicates only to those systems, you allowed.\n","description":"Mechanisms are the building blocks for rule specific pipelines and define the required behavior for these.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_mechanism_categories\"\u003eMechanism Categories\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll supported mechanisms fall into the following five categories, each implementing different mechanisms types (addressing different protocols or scenarios):\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"/docs/mechanisms/authenticators/\"\u003eAuthenticators\u003c/a\u003e, which inspect HTTP requests for presence of authentication objects, like e.g. the presence of a specific cookie. If such objects exist, authenticators verify the related authentication status and obtain information about the corresponding subject. A subject, could be a user who tries to use particular functionality of the upstream service, a machine (if you have machine-2-machine interaction), or something different. Authenticators ensure the subject is authenticated and the information available about it is valid.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"/docs/mechanisms/authorizers/\"\u003eAuthorizers\u003c/a\u003e, which ensure that the subject obtained via an authenticator has the required permissions to submit the given HTTP request and thus to execute the corresponding logic in the upstream service. E.g. a specific endpoint of the upstream service might only be accessible to a \u0026#34;user\u0026#34; from the \u0026#34;admin\u0026#34; group, or to an HTTP request if a specific HTTP header is set.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e, which enrich the information about the subject obtained via an authenticator with further contextual information, required either by the upstream service itself or an authorizer. This can be handy if the actual authentication system doesn’t have all information about the subject (which is usually the case in microservice architectures), or if dynamic information about the subject, like the current location based on the IP address, is required.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e, which, as the name implies, finalize the execution of the pipeline and enrich the request with data such as subject information or authentication tokens required by the upstream service. The available options range from doing nothing, adding a simple header over a structured JWT, to driving specific protocols, e.g. to obtain a token required by the upstream service.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"/docs/mechanisms/error_handlers/\"\u003eError Handlers\u003c/a\u003e, which are responsible for execution of logic if any of the mechanisms described above fail. These range from a simple error response to the client, which sent the request, to sophisticated ones, supporting complex logic and redirects.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAll mechanisms are stateless. Even some of them support caching, the corresponding data is not stored on the mechanisms level. A \u003ca href=\"/docs/operations/cache/\"\u003ecache backend\u003c/a\u003e is used instead, defaulting to an in-memory key-value store.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_mechanisms_catalogue\"\u003eMechanisms Catalogue\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThose mechanisms, which should be available for usage in rules, must be defined/configured first. That suits the following purposes:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eMechanisms are per se generic and must be configured for usage in particular use cases.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThat configuration provides useful default behavior addressing your particular requirements, like which identity management system to use, etc.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOnly those mechanisms, which are defined can be used in rules. With other words, if you do not define any mechanism, you cannot define any rule.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThat makes the definition of rules also very simple - just reference the required mechanisms and \u0026#34;tune\u0026#34; the configuration, specified in the catalogue only if required. Not everything can be tuned though.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIt also provides secure defaults. E.g. that way you can ensure heimdall communicates only to those systems, you allowed.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Concepts"],"tags":null,"title":"Mechanisms ","url":"/docs/concepts/mechanisms/"},{"categories":null,"content":" Emissary-Ingress is an Envoy-powered open source, high performance ingress controller and API Gateway for Kubernetes from Ambassador Labs. Integration happens by letting Emissary-Ingress delegating authentication and authorization to heimdall. If heimdall answers with a 2XX code, the ingress controller will grant access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\nPrerequisites Integration with Emissary-Ingress requires heimdall being operated in Decision Operation Mode.\nGlobal Configuration Integration with Emissary-Ingress can be achieved either\nby creating an AuthService resource for heimdall, or\nby creating an External Filter if you’re using the commercial Ambassador Edge Stack.\nIn both cases the underlying Envoy proxy will be configured to delegate authentication and authorization of all incoming requests for all routes to heimdall. The code snippet below shows the corresponding AuthService resource which configures Emissary Ingress to let Envoy communicate over the GRPC protocol with heimdall.\napiVersion: getambassador.io/v3alpha1 kind: AuthService metadata: name: heimdall namespace: heimdall spec: auth_service: \u0026#34;https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34; (1) proto: grpc protocol_version: v3 (2) 1 Configures the controller to use heimdall’s main service endpoint with \u0026lt;heimdall service name\u0026gt;, \u0026lt;namespace\u0026gt; and \u0026lt;port\u0026gt; depending on your configuration. If heimdall is not operated in the same namespace as the ingress controller, it is important to configure the full DNS, otherwise Envoy will not be able to resolve the IP of heimdall. 2 Sets the used Envoy’s ExtAuth GRPC protocol version to v3, as this is the only version supported by heimdall. If not set, Emissary will default to v2. The integration option shown above requires usage of the --envoy-grpc flag when starting heimdall. Unlike e.g. Contour, Emissary-Ingress allows however the usage of both, the Envoy’s external authorization GRPC protocol (used here), and the plain HTTP protocol. Route-Level configuration The single available configuration option on route level only supports disabling of request forwarding. That can be achieved by configuring a Mapping resource and setting bypass_auth to true (see also Bypass authentication).\nAdditional Resources Checkout the examples on GitHub for a working demo.\n","description":"This guide explains how to integrate heimdall with Emissary-Ingress Controller.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://www.getambassador.io/products/api-gateway\"\u003eEmissary-Ingress\u003c/a\u003e is an Envoy-powered open source, high performance ingress controller and API Gateway for Kubernetes from \u003ca href=\"https://www.getambassador.io/\"\u003eAmbassador Labs\u003c/a\u003e. Integration happens by letting Emissary-Ingress delegating authentication and authorization to heimdall. If heimdall answers with a 2XX code, the ingress controller will grant access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with Emissary-Ingress requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIntegration with Emissary-Ingress can be achieved either\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eby creating an \u003ca href=\"https://www.getambassador.io/docs/emissary/latest/topics/running/services/auth-service\"\u003e\u003ccode\u003eAuthService\u003c/code\u003e\u003c/a\u003e resource for heimdall, or\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eby creating an \u003ca href=\"https://www.getambassador.io/docs/edge-stack/latest/topics/using/filters/external\"\u003eExternal Filter\u003c/a\u003e if you’re using the commercial \u003ca href=\"https://www.getambassador.io/docs/edge-stack\"\u003eAmbassador Edge Stack\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both cases the underlying Envoy proxy will be configured to delegate authentication and authorization of all incoming requests for all routes to heimdall. The code snippet below shows the corresponding \u003ccode\u003eAuthService\u003c/code\u003e resource which configures Emissary Ingress to let Envoy communicate over the GRPC protocol with heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egetambassador.io/v3alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthService\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_service\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://\u0026lt;heimdall\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eservice\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eproto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egrpc\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprotocol_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ev3\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures the controller to use heimdall’s main service endpoint with \u003ccode\u003e\u0026lt;heimdall service name\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;namespace\u0026gt;\u003c/code\u003e and \u003ccode\u003e\u0026lt;port\u0026gt;\u003c/code\u003e depending on your configuration. If heimdall is not operated in the same namespace as the ingress controller, it is important to configure the full DNS, otherwise Envoy will not be able to resolve the IP of heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSets the used Envoy’s ExtAuth GRPC protocol version to v3, as this is the only version supported by heimdall. If not set, Emissary will default to v2.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe integration option shown above requires usage of the \u003ccode\u003e--envoy-grpc\u003c/code\u003e flag when starting heimdall. Unlike e.g. Contour, Emissary-Ingress allows however the usage of both, the \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto\"\u003eEnvoy’s external authorization GRPC\u003c/a\u003e protocol (used here), and the plain HTTP protocol.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_route_level_configuration\"\u003eRoute-Level configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe single available configuration option on route level only supports disabling of request forwarding. That can be achieved by configuring a \u003ca href=\"https://www.getambassador.io/docs/edge-stack/latest/topics/using/intro-mappings#introduction-to-the-mapping-resource\"\u003e\u003ccode\u003eMapping\u003c/code\u003e\u003c/a\u003e resource and setting \u003ccode\u003ebypass_auth\u003c/code\u003e to \u003ccode\u003etrue\u003c/code\u003e (see also \u003ca href=\"https://www.getambassador.io/docs/edge-stack/latest/topics/using/authservice#bypass-authentication\"\u003eBypass authentication\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCheckout the examples on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e for a working demo.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Emissary Ingress Integration","url":"/guides/proxies/emissary/"},{"categories":null,"content":" You can compare the relation between mechanisms and rules to a relation between a catalogue at a car dealer and a real car, when you get it. So, mechanisms is what you can see and select in a catalogue (though, in case of heimdall you have to define that catalogue first) to compile your car and the rule is your car with real components and behaviour. In that sense when you define a rule, you specify which mechanisms should it be built from and whether you would like some \u0026#34;tuning\u0026#34; to be applied to better suit your needs.\nRule Types Heimdall supports two types of rules:\nThe upstream specific rule, also called the regular rule. You can define as many regular rules, as required. These rules are dynamic by nature and can come and go together with the upstream service defining these.\nThe default rule, which, if defined, is used by the regular rules to inherit their behaviour and is also executed if no other rule matches.\nMemory Footprint Even the first paragraphs compare mechanisms and the rules with a catalogue of car parts and a real car, things are a bit more complex in reality.\nTo minimize the memory footprint, heimdall instanciates all defined mechanisms on start up. And since all mechanisms are stateless, following is happening at runtime, when the rule is loaded:\nIf a rule, respectively its pipeline just references a mechanism without providing additional configuration, the already instantiated mechanism is used.\nOtherwise, if the pipeline overrides any parts of the default mechanism configuration, a shallow copy of the referenced mechanism instance (created at start up) is created, and only those parts, which differ are replaced with new objects, representing the pipeline specific configuration.\nExecution of Rules The diagram below sketches the logic executed by heimdall for each and every incoming request.\nAny rule matching request? - This is the first step executed by heimdall in which it tries to find a matching rule. If there is no matching rule, heimdall either falls back to the default rule if available, or the request is denied. Otherwise, the rule specific authentication \u0026amp; authorization pipeline is executed.\nExecute authentication \u0026amp; authorization pipeline - when a rule is matched, the mechanisms defined in its authentication \u0026amp; authorization pipeline are executed.\nForward request, respectively respond to the API gateway - when the above steps succeed, heimdall, depending on the operating mode, responds with, respectively forwards whatever was defined in the pipeline (usually this is a set of HTTP headers). Otherwise\nExecute error pipeline is executed if any of the mechanisms, defined in the authentiction \u0026amp; authorization pipeline fail. This again results in a response, this time however, based on the definition in the used error handler.\nMatching of Rules As written above, an upstream specific rule is only executed when it matches an incoming request.\nThe actual matching happens via the requests URL path, which is guaranteed to happen with O(log(n)) time complexity and is based on the path expressions specified in the loaded rules. These expressions support usage of (named) wildcards to capture segments of the matched path. The implementation ensures, that more specific path expressions are matched first regardless of the placement of rules in a rule set.\nAdditional conditions, like the host, the HTTP method, or application of regular or glob expressions can also be taken into account, allowing different rules for the same path expressions. The information about the HTTP method, scheme, host, path and query is taken either from the request itself, or if present and allowed, from the X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Uri and X-Forwarded-Method headers of the incoming request.\nThere is also an option to have backtracking to a rule with a less specific path expression, if the actual specific path is matched, but the above said additional conditions are not satisfied.\nDefault Rule \u0026amp; Inheritance The Rule Types section tells, that a default rule can be used as a base to inherit behavior for the regular rule.\nIn principle, there is a need to differentiate two things:\nthe defined rule, which is what you define\nthe effective rule, which is what is executed at runtime\nThis is comparable to the polymorphism concept in programming languages. So, how does it work?\nImagine, the concept of a rule is e.g. an interface written in Java defining the following methods:\npublic interface Rule { public void executeAuthenticationStage(req Request) public void executeAuthorizationStage(req Request) public void executeFinalizationStage(req Request) public void handleError(req Request) } And the logic described in Execution of Rules is implemented similar to what is shown in the snippet below\nRule rule = findMatchingRule(req) if (rule == null) { throw new NotFoundError() } try { // execution of the authentication \u0026amp; authorization pipeline rule.executeAuthenticationStage(req) rule.executeAuthorizationStage(req) rule.executeFinalizationStage(req) // further logic related to response creation } catch(Exception e) { // execution of the error pipeline rule.handleError(req) // further logic related to response creation } with findMatchingRule returning a specific instance of a class implementing our Rule interface matching the request.\nSince there is some default behaviour in place, like error handling, if the error pipeline is empty, and some stages of the authentication \u0026amp; authorization pipeline is optional, internally, there is some kind of base rule in place, all other rules inherit from. So something like shown in the snippet below.\npublic abstract class BaseRule implements Rule { public abstract void executeAuthenticationStage(req Request) public void executeAuthorizationStage(req Request) {} public void executeFinalizationStage(req Request) {} public void handleError(req Request) { handlerErrorDefault(req) } } If there is no default rule configured, an upstream specific rule can then be considered as a class inheriting from that BaseRule and must implement at least the executeAuthenticationStage method, similar to what is shown below\npublic class MySpecificRule extends BaseRule { public void executeAuthenticationStage(req Request) { ... } } If however, there is a default rule configured, on one hand, it can be considered as yet another class deriving from our BaseClass. So, something like\npublic class DefaultRule extends BaseRule { public void executeAuthenticationStage(req Request) { ... } public void executeAuthorizationStage(req Request) { ... } public void executeFinalizationStage(req Request) { ... } public void handleError(req Request) { ... } } with at least the aforesaid executeAuthenticationStage method being implemented, as this is also required for the regular rule.\nOn the other hand, the definition of a regular, respectively upstream specific rule is then not a class deriving from the BaseRule, but from the DefaultRule. That way, upstream specific rules are only required, if the behavior of the default rule would not fit the given requirements of a particular service, respectively endpoint. So, if e.g. a rule requires only the authentication stage to be different from the default rule, you would only specify the required authentication mechanisms. That would result in something like shown in the snippet below.\npublic class SpecificRule extends DefaultRule { public void executeAuthenticationStage(req Request) { ... } } And if there is a need to have the authorization stage deviating from the default rule, you would only specify the required authorization and contextualization mechanisms, resulting in something like\npublic class SpecificRule extends DefaultRule { public void executeAuthorizationStage(req Request) { ... } } You cannot override a single mechanism of a particular stage. As soon as you define a single mechanism in a pipeline, belonging to the one or the other stage, the entire stage is overridden. ","description":"Rules defines what should happen to particular requests and under which conditions. They assemble the authentication \u0026 authorization and error pipelines and bring previously configured mechanisms to life.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can compare the relation between mechanisms and rules to a relation between a catalogue at a car dealer and a real car, when you get it. So, mechanisms is what you can see and select in a catalogue (though, in case of heimdall you have to define that catalogue first) to compile your car and the rule is your car with real components and behaviour. In that sense when you define a rule, you specify which mechanisms should it be built from and whether you would like some \u0026#34;tuning\u0026#34; to be applied to better suit your needs.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_rule_types\"\u003eRule Types\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall supports two types of rules:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ca href=\"/docs/rules/regular_rule/\"\u003eupstream specific rule\u003c/a\u003e, also called the regular rule. You can define as many regular rules, as required. These rules are dynamic by nature and can come and go together with the upstream service defining these.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe \u003ca href=\"/docs/rules/regular_rule/\"\u003edefault rule\u003c/a\u003e, which, if defined, is used by the regular rules to inherit their behaviour and is also executed if no other rule matches.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_memory_footprint\"\u003eMemory Footprint\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEven the first paragraphs compare mechanisms and the rules with a catalogue of car parts and a real car, things are a bit more complex in reality.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo minimize the memory footprint, heimdall instanciates all defined mechanisms on start up. And since all mechanisms are stateless, following is happening at runtime, when the rule is loaded:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIf a rule, respectively its pipeline just references a mechanism without providing additional configuration, the already instantiated mechanism is used.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOtherwise, if the pipeline overrides any parts of the default mechanism configuration, a shallow copy of the referenced mechanism instance (created at start up) is created, and only those parts, which differ are replaced with new objects, representing the pipeline specific configuration.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_execution_of_rules\"\u003eExecution of Rules\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe diagram below sketches the logic executed by heimdall for each and every incoming request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-95b0331829cfd516daf370f547944674.svg\" alt=\"Diagram\" width=\"820\" height=\"546\"/\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eAny rule matching request?\u003c/strong\u003e - This is the first step executed by heimdall in which it tries to find a \u003ca href=\"#_matching_of_rules\"\u003ematching rule\u003c/a\u003e. If there is no matching rule, heimdall either falls back to the default rule if available, or the request is denied. Otherwise, the rule specific authentication \u0026amp; authorization pipeline is executed.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eExecute authentication \u0026amp; authorization pipeline\u003c/strong\u003e - when a rule is matched, the mechanisms defined in its authentication \u0026amp; authorization pipeline are executed.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eForward request, respectively respond to the API gateway\u003c/strong\u003e - when the above steps succeed, heimdall, depending on the \u003ca href=\"/docs/concepts/operating_modes/\"\u003eoperating mode\u003c/a\u003e, responds with, respectively forwards whatever was defined in the pipeline (usually this is a set of HTTP headers). Otherwise\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eExecute error pipeline\u003c/strong\u003e is executed if any of the mechanisms, defined in the authentiction \u0026amp; authorization pipeline fail. This again results in a response, this time however, based on the definition in the used error handler.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_matching_of_rules\"\u003eMatching of Rules\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs written above, an \u003ca href=\"/docs/rules/regular_rule/\"\u003eupstream specific rule\u003c/a\u003e is only executed when it matches an incoming request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual matching happens via the requests URL path, which is guaranteed to happen with O(log(n)) time complexity and is based on the path expressions specified in the loaded rules. These expressions support usage of (named) wildcards to capture segments of the matched path. The implementation ensures, that more specific path expressions are matched first regardless of the placement of rules in a \u003ca href=\"/docs/concepts/provider/#_rule_sets\"\u003erule set\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAdditional conditions, like the host, the HTTP method, or application of regular or glob expressions can also be taken into account, allowing different rules for the same path expressions. The information about the HTTP method, scheme, host, path and query is taken either from the request itself, or if present and allowed, from the \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e and \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e headers of the incoming request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere is also an option to have backtracking to a rule with a less specific path expression, if the actual specific path is matched, but the above said additional conditions are not satisfied.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_default_rule_inheritance\"\u003eDefault Rule \u0026amp; Inheritance\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"#_rule_types\"\u003eRule Types\u003c/a\u003e section tells, that a default rule can be used as a base to inherit behavior for the regular rule.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn principle, there is a need to differentiate two things:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ethe defined rule, which is what you define\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe effective rule, which is what is executed at runtime\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis is comparable to the polymorphism concept in programming languages. So, how does it work?\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine, the concept of a rule is e.g. an interface written in Java defining the following methods:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003einterface\u003c/span\u003e \u003cspan class=\"nc\"\u003eRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthorizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteFinalizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003ehandleError\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAnd the logic described in \u003ca href=\"#_execution_of_rules\"\u003eExecution of Rules\u003c/a\u003e is implemented similar to what is shown in the snippet below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"nc\"\u003eRule\u003c/span\u003e \u003cspan class=\"n\"\u003erule\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003efindMatchingRule\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n\u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003erule\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nf\"\u003eNotFoundError\u003c/span\u003e\u003cspan class=\"o\"\u003e()\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"k\"\u003etry\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e// execution of the authentication \u0026amp; authorization pipeline\u003c/span\u003e\n \u003cspan class=\"n\"\u003erule\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"n\"\u003erule\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003eexecuteAuthorizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"n\"\u003erule\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003eexecuteFinalizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n\n \u003cspan class=\"c1\"\u003e// further logic related to response creation\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003ecatch\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"nc\"\u003eException\u003c/span\u003e \u003cspan class=\"n\"\u003ee\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e// execution of the error pipeline\u003c/span\u003e\n \u003cspan class=\"n\"\u003erule\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003ehandleError\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n\n \u003cspan class=\"c1\"\u003e// further logic related to response creation\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ewith \u003ccode\u003efindMatchingRule\u003c/code\u003e returning a specific instance of a class implementing our \u003ccode\u003eRule\u003c/code\u003e interface matching the request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince there is some default behaviour in place, like error handling, if the error pipeline is empty, and some stages of the authentication \u0026amp; authorization pipeline is optional, internally, there is some kind of base rule in place, all other rules inherit from. So something like shown in the snippet below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eabstract\u003c/span\u003e \u003cspan class=\"kd\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eBaseRule\u003c/span\u003e \u003cspan class=\"kd\"\u003eimplements\u003c/span\u003e \u003cspan class=\"nc\"\u003eRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eabstract\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthorizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{}\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteFinalizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{}\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003ehandleError\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"n\"\u003ehandlerErrorDefault\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf there is no default rule configured, an upstream specific rule can then be considered as a class inheriting from that \u003ccode\u003eBaseRule\u003c/code\u003e and must implement at least the \u003ccode\u003eexecuteAuthenticationStage\u003c/code\u003e method, similar to what is shown below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eMySpecificRule\u003c/span\u003e \u003cspan class=\"kd\"\u003eextends\u003c/span\u003e \u003cspan class=\"nc\"\u003eBaseRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf however, there is a default rule configured, on one hand, it can be considered as yet another class deriving from our \u003ccode\u003eBaseClass\u003c/code\u003e. So, something like\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eDefaultRule\u003c/span\u003e \u003cspan class=\"kd\"\u003eextends\u003c/span\u003e \u003cspan class=\"nc\"\u003eBaseRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthorizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteFinalizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003ehandleError\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ewith at least the aforesaid \u003ccode\u003eexecuteAuthenticationStage\u003c/code\u003e method being implemented, as this is also required for the regular rule.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOn the other hand, the definition of a regular, respectively upstream specific rule is then not a class deriving from the \u003ccode\u003eBaseRule\u003c/code\u003e, but from the \u003ccode\u003eDefaultRule\u003c/code\u003e. That way, upstream specific rules are only required, if the behavior of the default rule would not fit the given requirements of a particular service, respectively endpoint. So, if e.g. a rule requires only the authentication stage to be different from the default rule, you would only specify the required authentication mechanisms. That would result in something like shown in the snippet below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eSpecificRule\u003c/span\u003e \u003cspan class=\"kd\"\u003eextends\u003c/span\u003e \u003cspan class=\"nc\"\u003eDefaultRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthenticationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAnd if there is a need to have the authorization stage deviating from the default rule, you would only specify the required authorization and contextualization mechanisms, resulting in something like\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"java\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eSpecificRule\u003c/span\u003e \u003cspan class=\"kd\"\u003eextends\u003c/span\u003e \u003cspan class=\"nc\"\u003eDefaultRule\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\"\u003eexecuteAuthorizationStage\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ereq\u003c/span\u003e \u003cspan class=\"nc\"\u003eRequest\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e{\u003c/span\u003e \u003cspan class=\"o\"\u003e...\u003c/span\u003e \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nYou cannot override a single mechanism of a particular stage. As soon as you define a single mechanism in a pipeline, belonging to the one or the other stage, the entire stage is overridden.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Concepts"],"tags":null,"title":"Rules ","url":"/docs/concepts/rules/"},{"categories":null,"content":" Envoy is a high performance distributed proxy designed for single services and applications, as well as a communication bus and “universal data plane” designed for large microservice “service mesh” architectures.\nPrerequisites Integration with Envoy proxy requires heimdall being operated in Decision Operation Mode.\nIntegration Options Envoy makes integration with external authorization services, like heimdall possible via an External Authorization filter in two ways\neither via HTTP\nor via GRPC\nIn both cases, the filter calls an external gRPC or HTTP service to check whether an incoming HTTP request is authorized or not. If the request is deemed unauthorized, then the request will be denied normally with 403 (Forbidden) response.\nEven envoy allows the authorization service sending additional custom metadata to the upstream when GRPC is used, heimdall does not make use of this option. Global Configuration To integrate heimdall with Envoy globally, you need to configure two things:\na cluster entry referencing the actual heimdall address, and\nthe aforesaid filter in the http filter chain\nThe following snippet provides an example on how to create a cluster instance referencing heimdall. It assumes, you have just one heimdall instance deployed, which is also available via heimdall DNS name.\nclusters: # other cluster entries - name: ext-authz (1) type: strict_dns typed_extension_protocol_options: (2) envoy.extensions.upstreams.http.v3.HttpProtocolOptions: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions\u0026#34; explicit_http_config: http2_protocol_options: {} load_assignment: (3) cluster_name: ext-authz endpoints: - lb_endpoints: - endpoint: address: socket_address: address: heimdall port_value: 4455 # other cluster entries 1 The name of our cluster 2 Here, we configure envoy to communicate with heimdall by making use of HTTP 2. This configuration is only required if you want to integrate heimdall via Envoy’s grpc_service (see below), as otherwise envoy will use HTTP 1 for GRPC communication, which is actually not allowed by GRPC (only HTTP 2 is supported). 3 The endpoints in the cluster. In this example, only one endpoint is configured. You can now include an External Authorization HTTP filter in the definition of the HTTP connection manager and depending on the used configuration, either configure the http_service and let it contain the required header name(s), heimdall sets in the HTTP responses (depends on your Contextualizers and Finalizers configuration), or configure the grpc_service.\nUsing HTTP protocol The following snipped shows, how an External Authorization can be defined using http_service to let Envoy communicating with heimdall by making use of the previously defined cluster (see snippet from above) as well as forwarding all request headers to heimdall and to let it forward headers, set by heimdall in its responses (here the Authorization header) to the upstream services.\nhttp_filters: # other http filter - name: envoy.filters.http.ext_authz typed_config: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34; (1) transport_api_version: V3 (2) http_service: server_uri: (3) uri: heimdall:4455 cluster: ext-authz timeout: 0.25s authorization_request: allowed_headers: (4) patterns: - safe_regex: google_re2: {} regex: \u0026#34;.*\u0026#34; authorization_response: (5) allowed_upstream_headers: patterns: - exact: authorization # other http filter 1 The type of the filter, we’re going to configure 2 Heimdall supports only the version 3 of the GRPC protocol defined by Envoy for that filter. So we set the required version here. 3 The reference to our previously configured cluster 4 Here, we say envoy to forward all headers from the received request to heimdall 5 And here, we instruct envoy to forward the Authorization header set bei heimdall in its response to envoy to the upstream service Envoy does not set X-Forwarded-* headers, as long as the envoy.filters.http.dynamic_forward_proxy is not configured. In such cases matching of URLs happens based on those URLs, used by Envoy while communicating with heimdall. That means your rules should ignore the scheme and host parts, respectively use the values specific for heimdall and not of the domain. Please follow Security Considerations if your rules rely on any of the X-Forwarded-* headers, and you integrate heimdall with envoy using http_service.\nIf you integrate heimdall with envoy via grpc_service (see below), spoofing of the aforesaid headers is not possible.\nUsing GRPC protocol The following snipped shows, how an External Authorization can be defined using grpc_service to let Envoy communicating with heimdall by making use of the previously defined cluster (see snippet from above). In that configuration envoy by default forwards all request header to heimdall and also forwards headers, set by heimdall in its responses to the upstream services.\nhttp_filters: # other http filter - name: envoy.filters.http.ext_authz typed_config: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34; (1) transport_api_version: V3 (2) grpc_service: (3) envoy_grpc: cluster_name: ext-authz # other http filter 1 The type of the filter, we’re going to configure. Same filter is used for both approaches, communication via HTTP and GRPC 2 Heimdall supports only the version 3 of the GRPC protocol defined by Envoy for that filter. So we set the required version here 3 The reference to our previously configured cluster Route-based Configuration Route base configuration happens exactly the same way as globally. There is also an option to fine tune or disable the external authorization service if required by making use of the ExtAuthzPerRoute filter. You can find an example in the official Envoy documentation.\nDemo Setup The Envoy configuration file shown below can be used to create a fully working setup based on the quickstart described in Protect an Application and set up to implement Edge-level Authorization Architecture. Just update the docker-compose.yaml file used in that guide and replace the entry for proxy service, with the one shown below. You can also remove all labels configurations, as these will have no effect.\n# docker-compose.yaml services: proxy: image: envoyproxy/envoy:v1.24.1 volumes: - ./envoy.yaml:/envoy.yaml:ro ports: - 9090:9090 command: -c /envoy.yaml # other services from the guide # envoy.yaml static_resources: listeners: - name: listener_0 address: socket_address: address: 0.0.0.0 port_value: 9090 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\u0026#34; stat_prefix: edge http_filters: - name: envoy.filters.http.ext_authz typed_config: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34; transport_api_version: V3 http_service: server_uri: uri: heimdall:4455 cluster: ext-authz timeout: 0.25s authorization_request: allowed_headers: patterns: - safe_regex: google_re2: {} regex: \u0026#34;.*\u0026#34; authorization_response: allowed_upstream_headers: patterns: - exact: authorization - name: envoy.filters.http.router typed_config: \u0026#34;@type\u0026#34;: \u0026#34;type.googleapis.com/envoy.extensions.filters.http.router.v3.Router\u0026#34; route_config: virtual_hosts: - name: direct_response_service domains: [\u0026#34;*\u0026#34;] routes: - match: prefix: \u0026#34;/\u0026#34; route: cluster: services clusters: - name: ext-authz type: strict_dns load_assignment: cluster_name: ext-authz endpoints: - lb_endpoints: - endpoint: address: socket_address: address: heimdall port_value: 4455 - name: services connect_timeout: 5s type: strict_dns dns_lookup_family: V4_ONLY load_assignment: cluster_name: services endpoints: - lb_endpoints: - endpoint: address: socket_address: address: upstream port_value: 80 After starting the docker compose environment, you can run the curl commands shown in the referenced guide. This time however against envoy by using port 9090. E.g. $ curl -v 127.0.0.1:9090/anonymous.\nAdditional Resources The demo setup shown above is also available on GitHub.\n","description":"This guide explains how to integrate heimdall with Envoy.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://www.envoyproxy.io/\"\u003eEnvoy\u003c/a\u003e is a high performance distributed proxy designed for single services and applications, as well as a communication bus and “universal data plane” designed for large microservice “service mesh” architectures.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with Envoy proxy requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_integration_options\"\u003eIntegration Options\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnvoy makes integration with external authorization services, like heimdall possible via an \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e filter in two ways\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eeither via HTTP\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eor via GRPC\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both cases, the filter calls an external gRPC or HTTP service to check whether an incoming HTTP request is authorized or not. If the request is deemed unauthorized, then the request will be denied normally with 403 (Forbidden) response.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nEven envoy allows the authorization service sending additional custom metadata to the upstream when GRPC is used, heimdall does not make use of this option.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo integrate heimdall with Envoy globally, you need to configure two things:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ea \u003ccode\u003ecluster\u003c/code\u003e entry referencing the actual heimdall address, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe aforesaid filter in the http filter chain\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet provides an example on how to create a \u003ccode\u003ecluster\u003c/code\u003e instance referencing heimdall. It assumes, you have just one heimdall instance deployed, which is also available via \u003ccode\u003eheimdall\u003c/code\u003e DNS name.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eclusters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other cluster entries\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003estrict_dns\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_extension_protocol_options\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eenvoy.extensions.upstreams.http.v3.HttpProtocolOptions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexplicit_http_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp2_protocol_options\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eload_assignment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ecluster_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003elb_endpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esocket_address\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport_value\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4455\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other cluster entries\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe name of our cluster\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we configure envoy to communicate with heimdall by making use of HTTP 2. This configuration is only required if you want to integrate heimdall via Envoy’s \u003ccode\u003egrpc_service\u003c/code\u003e (see below), as otherwise envoy will use HTTP 1 for GRPC communication, which is actually not allowed by GRPC (only HTTP 2 is supported).\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe endpoints in the cluster. In this example, only one endpoint is configured.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can now include an \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e HTTP filter in the definition of the HTTP connection manager and depending on the used configuration, either configure the \u003ccode\u003ehttp_service\u003c/code\u003e and let it contain the required header name(s), heimdall sets in the HTTP responses (depends on your \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration), or configure the \u003ccode\u003egrpc_service\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_using_http_protocol\"\u003eUsing HTTP protocol\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snipped shows, how an \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e can be defined using \u003ccode\u003ehttp_service\u003c/code\u003e to let Envoy communicating with heimdall by making use of the previously defined \u003ccode\u003ecluster\u003c/code\u003e (see snippet from above) as well as forwarding all request headers to heimdall and to let it forward headers, set by heimdall in its responses (here the \u003ccode\u003eAuthorization\u003c/code\u003e header) to the upstream services.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ehttp_filters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other http filter\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoy.filters.http.ext_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etransport_api_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eV3\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ehttp_service\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eserver_uri\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003euri\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall:4455\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e0.25s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_request\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003epatterns\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003esafe_regex\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egoogle_re2\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eregex\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e.*\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_response\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eallowed_upstream_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epatterns\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexact\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthorization\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other http filter\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe type of the filter, we’re going to configure\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHeimdall supports only the version 3 of the GRPC protocol defined by Envoy for that filter. So we set the required version here.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe reference to our previously configured cluster\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we say envoy to forward all headers from the received request to heimdall\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAnd here, we instruct envoy to forward the \u003ccode\u003eAuthorization\u003c/code\u003e header set bei heimdall in its response to envoy to the upstream service\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnvoy does not set \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers, as long as the \u003ccode\u003eenvoy.filters.http.dynamic_forward_proxy\u003c/code\u003e is not configured. In such cases matching of URLs happens based on those URLs, used by Envoy while communicating with heimdall. That means your rules should ignore the scheme and host parts, respectively use the values specific for heimdall and not of the domain. Please follow \u003ca href=\"/docs/operations/security/#_http_headers_security_considerations\"\u003eSecurity Considerations\u003c/a\u003e if your rules rely on any of the \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers, and you integrate heimdall with envoy using \u003ccode\u003ehttp_service\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you integrate heimdall with envoy via \u003ccode\u003egrpc_service\u003c/code\u003e (see below), spoofing of the aforesaid headers is not possible.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_using_grpc_protocol\"\u003eUsing GRPC protocol\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snipped shows, how an \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e can be defined using \u003ccode\u003egrpc_service\u003c/code\u003e to let Envoy communicating with heimdall by making use of the previously defined \u003ccode\u003ecluster\u003c/code\u003e (see snippet from above). In that configuration envoy by default forwards all request header to heimdall and also forwards headers, set by heimdall in its responses to the upstream services.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ehttp_filters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other http filter\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoy.filters.http.ext_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etransport_api_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eV3\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003egrpc_service\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eenvoy_grpc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other http filter\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe type of the filter, we’re going to configure. Same filter is used for both approaches, communication via HTTP and GRPC\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHeimdall supports only the version 3 of the GRPC protocol defined by Envoy for that filter. So we set the required version here\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe reference to our previously configured cluster\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_route_based_configuration\"\u003eRoute-based Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRoute base configuration happens exactly the same way as globally. There is also an option to fine tune or disable the external authorization service if required by making use of the \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto#envoy-v3-api-msg-extensions-filters-http-ext-authz-v3-extauthzperroute\"\u003eExtAuthzPerRoute\u003c/a\u003e filter. You can find an example in the official \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/ext_authz_filter.html#per-route-configuration\"\u003eEnvoy documentation\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_demo_setup\"\u003eDemo Setup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe Envoy configuration file shown below can be used to create a fully working setup based on the quickstart described in \u003ca href=\"/docs/getting_started/protect_an_app/\"\u003eProtect an Application\u003c/a\u003e and set up to implement Edge-level Authorization Architecture. Just update the \u003ccode\u003edocker-compose.yaml\u003c/code\u003e file used in that guide and replace the entry for \u003ccode\u003eproxy\u003c/code\u003e service, with the one shown below. You can also remove all \u003ccode\u003elabels\u003c/code\u003e configurations, as these will have no effect.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# docker-compose.yaml\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eproxy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoyproxy/envoy:v1.24.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./envoy.yaml:/envoy.yaml:ro\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e9090:9090\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e-c /envoy.yaml\u003c/span\u003e\n\n \u003cspan class=\"c1\"\u003e# other services from the guide\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# envoy.yaml\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003estatic_resources\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elisteners\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003elistener_0\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esocket_address\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e0.0.0.0\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport_value\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e9090\u003c/span\u003e\n \u003cspan class=\"na\"\u003efilter_chains\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efilters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoy.filters.network.http_connection_manager\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003estat_prefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eedge\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_filters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoy.filters.http.ext_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003etransport_api_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eV3\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_service\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eserver_uri\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euri\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall:4455\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e0.25s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_request\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epatterns\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003esafe_regex\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egoogle_re2\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eregex\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e.*\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_response\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_upstream_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epatterns\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexact\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthorization\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eenvoy.filters.http.router\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.filters.http.router.v3.Router\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroute_config\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evirtual_hosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edirect_response_service\u003c/span\u003e\n \u003cspan class=\"na\"\u003edomains\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e*\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e/\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservices\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eclusters\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003estrict_dns\u003c/span\u003e\n \u003cspan class=\"na\"\u003eload_assignment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003elb_endpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esocket_address\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport_value\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4455\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservices\u003c/span\u003e\n \u003cspan class=\"na\"\u003econnect_timeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003estrict_dns\u003c/span\u003e\n \u003cspan class=\"na\"\u003edns_lookup_family\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eV4_ONLY\u003c/span\u003e\n \u003cspan class=\"na\"\u003eload_assignment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservices\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003elb_endpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esocket_address\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport_value\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e80\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAfter starting the docker compose environment, you can run the curl commands shown in the referenced guide. This time however against envoy by using port 9090. E.g. \u003ccode\u003e$ curl -v 127.0.0.1:9090/anonymous\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe demo setup shown above is also available on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Envoy Integration","url":"/guides/proxies/envoy/"},{"categories":null,"content":" Rules Sets Regular, respectively upstream specific rules must somehow be organized, versioned and also loaded. So, there must be some structure allowing all of that. That structure is defined by the so-called rule sets.\nA rule set can be considered to be just a file containing a list of rules and some additional meta information, like format version, name of the rule set and alike. Rule sets do also allow ordering of rules, e.g. with most specific matching expressions first allowing simpler matching expressions.\nThe actual format of the rule set is provider specific.\nProvider Types While all providers are different in the sense that they support different sources to load rule sets from, respectively monitor them, most of the providers use the same rule set format.\nThe following table gives an overview about existing providers\nProvider Rule Set Format Short Description File-System\nYAML or JSON\nLoads rule set files from the local file system\nHTTP Endpoint\nYAML or JSON\nLoads rule sets from an HTTP(s) endpoint\nCloud Blob\nYAML or JSON\nLoads rule sets from cloud blobs, like AWS S3, Google Cloud Storage, Azure Cloud Storage and alike.\nKubernetes\nCustom Resource\nLoads rule sets made available to a kubernetes cluster as customer resources.\n","description":"When rules define the behavior in sense of the desired authentication and authorization aspects, then the providers are those entities, which manage the lifecycle of these. That are the providers, which load, reload or remove rules when new rules appears, changes are detected, or rules are deleted.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_rules_sets\"\u003eRules Sets\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRegular, respectively upstream specific rules must somehow be organized, versioned and also loaded. So, there must be some structure allowing all of that. That structure is defined by the so-called rule sets.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA rule set can be considered to be just a file containing a list of rules and some additional meta information, like format version, name of the rule set and alike. Rule sets do also allow ordering of rules, e.g. with most specific matching expressions first allowing simpler matching expressions.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual format of the rule set is provider specific.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_provider_types\"\u003eProvider Types\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhile all providers are different in the sense that they support different sources to load rule sets from, respectively monitor them, most of the providers use the same rule set format.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following table gives an overview about existing providers\u003c/p\u003e\n\u003c/div\u003e\n\u003ctable class=\"tableblock frame-all grid-all stretch\"\u003e\n\u003ccolgroup\u003e\n\u003ccol style=\"width: 22.2222%;\"/\u003e\n\u003ccol style=\"width: 22.2222%;\"/\u003e\n\u003ccol style=\"width: 55.5556%;\"/\u003e\n\u003c/colgroup\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eProvider\u003c/strong\u003e\u003c/th\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eRule Set Format\u003c/strong\u003e\u003c/th\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eShort Description\u003c/strong\u003e\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ca href=\"/docs/rules/providers/#_filesystem\"\u003eFile-System\u003c/a\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eYAML or JSON\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eLoads rule set files from the local file system\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ca href=\"/docs/rules/providers/#_http_endpoint\"\u003eHTTP Endpoint\u003c/a\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eYAML or JSON\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eLoads rule sets from an HTTP(s) endpoint\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ca href=\"/docs/rules/providers/#_cloud_blob\"\u003eCloud Blob\u003c/a\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eYAML or JSON\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eLoads rule sets from cloud blobs, like AWS S3, Google Cloud Storage, Azure Cloud Storage and alike.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ca href=\"/docs/rules/providers/#_kubernetes\"\u003eKubernetes\u003c/a\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eCustom Resource\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eLoads rule sets made available to a kubernetes cluster as customer resources.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Concepts"],"tags":null,"title":"Rule Provider","url":"/docs/concepts/provider/"},{"categories":null,"content":" Envoy Gateway is an open source project for managing Envoy Proxy as a Kubernetes-based application gateway by making use of the Gateway API resources.\nPrerequisites A kubernetes cluster\nDeployed Envoy Gateway (See here for installation options)\nDeployed GatewayClass resource that matches Envoy Gateway’s configured controllerName (typically gateway.envoyproxy.io/gatewayclass-controller), as well as a deployed Gateway resource.\nheimdall installed and operated in Decision Operation Mode.\nIntegration Options Technically, the integration happens the same way as with Envoy itself by making use of the External Authorization filter, and can be done in two ways:\neither via HTTP\nor via gRPC (recommended)\nIn both cases, the filter calls an external gRPC or HTTP service (here heimdall) to check whether an incoming HTTP request is authorized or not. If heimdall responses with 2xx the request is forwarded to the upstream service, otherwise the response from heimdall is returned to the caller.\nIn case of Envoy Gateway the abovesaid configuration happens via a SecurityPolicy custom resource, that can be linked to a Gateway, HTTPRoute, or a GRPCRoute resource.\nAs of today, there is a limitation in the implementation of the Envoy Gateway - it does not allow cross-namespace reference of external auth services (see also envoyproxy/gateway#3322). That means, the HTTPRoute, the Gateway resource and heimdall must be deployed in the same namespace. Global Configuration To integrate heimdall with the gateway globally, that is, each and every request will be forwarded to heimdall for authentication and authorization purposes first, create a SecurityPolicy as shown below in the namespace, the Gateway resource is deployed into.\napiVersion: gateway.envoyproxy.io/v1alpha1 kind: SecurityPolicy metadata: name: ext-auth-heimdall (1) namespace: heimdall (2) spec: targetRef: (3) group: gateway.networking.k8s.io kind: Gateway name: eg namespace: heimdall extAuth: grpc: backendRef: (4) name: heimdall port: 4455 namespace: heimdall 1 The name of the SecurityPolicy. You can change it to any other value if you like. 2 The namespace for the policy. It must be the same namespace the Gateway resource and heimdall are deployed into. So change it to your namespace. 3 Defines the Gateway resource, this policy should be applied to. Change the name property to the name of your Gateway resource and the namespace property to the proper namespace (same as in 2) 4 Defines the reference to the heimdall Service using the gRPC protocol. Change the name and the namespace to the proper values of your setup. Route-level Configuration The integration on the route level happens similar to the global integration. The difference is that the SecurityPolicy is applied to an HTTPRoute as shown below and not the Gateway resource.\napiVersion: gateway.envoyproxy.io/v1alpha1 kind: SecurityPolicy metadata: name: ext-auth-example (1) namespace: heimdall (2) spec: targetRef: (3) group: gateway.networking.k8s.io kind: HTTPRoute name: heimdall extAuth: grpc: backendRef: (4) name: heimdall port: 4455 namespace: heimdall 1 The name of the SecurityPolicy. You can change it to any other value if you like. 2 The namespace for the policy. It must be the same namespace the HTTPRoute resource is deployed into, so the namespace, your application is deployed to. So change it to your namespace. 3 Defines the HTTPRoute resource, this policy should be applied to. Change the name property to the name of your HTTPRoute resource and the namespace property to the proper namespace (same as in 2) 4 Defines the reference to the heimdall Service using the gRPC protocol. Change the name and the namespace to the proper values of your setup. Security Considerations The configuration options shown above are highly insecure, as the communication from the gateway to heimdall happens over plain HTTP. Therefore, it is highly recommended to enable TLS. This can be achieved by enabling TLS for heimdall and attaching a BackendTLSPolicy resource shown below to heimdall’s Service.\napiVersion: gateway.networking.k8s.io/v1alpha2 kind: BackendTLSPolicy metadata: name: heimdall-btls namespace: heimdall (1) spec: targetRef: (2) group: \u0026#39;\u0026#39; kind: Service namespace: heimdall name: heimdall sectionName: \u0026#34;4455\u0026#34; tls: (3) caCertRefs: - name: demo-ca (4) group: \u0026#39;\u0026#39; kind: ConfigMap hostname: heimdall (5) 1 Change it to the namespace in which heimdall is deployed 2 The reference to heimdall’s Service. Change the name and the namespace to the proper values. 3 Here we configure the reference to the ConfigMap with the certificate of the CA, used to issue a TLS server authentication certificate for heimdall, as well as the hostname used by heimdall (and present in the SAN extension of heimdall’s TLS certificate). The ConfigMap must be in the same namespace as the BackendTLSPolicy. 4 The name of the ConfigMap. Change it to the proper value. 5 The expected hostname used by heimdall. Change it to the proper value. Additional Resources A fully working example with Envoy Gateway is also available on GitHub.\nYou can find the official external authentication guide for Envoy Gateway here. It contains a fully working setup with a demo application.\nSecure Gateways is a highly recommended read as well.\n","description":"This guide explains how to integrate heimdall with Envoy Gateway.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://gateway.envoyproxy.io\"\u003eEnvoy Gateway\u003c/a\u003e is an open source project for managing \u003ca href=\"https://www.envoyproxy.io/\"\u003eEnvoy Proxy\u003c/a\u003e as a Kubernetes-based application gateway by making use of the \u003ca href=\"https://gateway-api.sigs.k8s.io/\"\u003eGateway API\u003c/a\u003e resources.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eA kubernetes cluster\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDeployed Envoy Gateway (See \u003ca href=\"https://gateway.envoyproxy.io/v1.0.1/install/\"\u003ehere\u003c/a\u003e for installation options)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDeployed \u003ca href=\"https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.GatewayClass\"\u003e\u003ccode\u003eGatewayClass\u003c/code\u003e\u003c/a\u003e resource that matches Envoy Gateway’s configured \u003ccode\u003econtrollerName\u003c/code\u003e (typically \u003ccode\u003egateway.envoyproxy.io/gatewayclass-controller\u003c/code\u003e), as well as a deployed \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e resource.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eheimdall installed and operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_integration_options\"\u003eIntegration Options\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTechnically, the integration happens the same way as with \u003ca href=\"/guides/proxies/envoy/\"\u003eEnvoy\u003c/a\u003e itself by making use of the \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e filter, and can be done in two ways:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eeither via HTTP\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eor via gRPC (recommended)\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both cases, the filter calls an external gRPC or HTTP service (here heimdall) to check whether an incoming HTTP request is authorized or not. If heimdall responses with \u003ccode\u003e2xx\u003c/code\u003e the request is forwarded to the upstream service, otherwise the response from heimdall is returned to the caller.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn case of Envoy Gateway the abovesaid configuration happens via a \u003ca href=\"https://gateway.envoyproxy.io/contributions/design/security-policy/\"\u003e\u003ccode\u003eSecurityPolicy\u003c/code\u003e\u003c/a\u003e custom resource, that can be linked to a \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/httproute\"\u003e\u003ccode\u003eHTTPRoute\u003c/code\u003e\u003c/a\u003e, or a \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/grpcroute\"\u003e\u003ccode\u003eGRPCRoute\u003c/code\u003e\u003c/a\u003e resource.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAs of today, there is a limitation in the implementation of the Envoy Gateway - it does not allow cross-namespace reference of external auth services (see also \u003ca href=\"https://github.com/envoyproxy/gateway/issues/3322\"\u003eenvoyproxy/gateway#3322\u003c/a\u003e). That means, the \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/httproute\"\u003e\u003ccode\u003eHTTPRoute\u003c/code\u003e\u003c/a\u003e, the \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e resource and heimdall must be deployed in the same namespace.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo integrate heimdall with the gateway globally, that is, each and every request will be forwarded to heimdall for authentication and authorization purposes first, create a \u003ca href=\"https://gateway.envoyproxy.io/contributions/design/security-policy/\"\u003e\u003ccode\u003eSecurityPolicy\u003c/code\u003e\u003c/a\u003e as shown below in the namespace, the \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e resource is deployed into.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egateway.envoyproxy.io/v1alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSecurityPolicy\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-auth-heimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etargetRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003egroup\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egateway.networking.k8s.io\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGateway\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eeg\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eextAuth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egrpc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebackendRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4455\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe name of the \u003ccode\u003eSecurityPolicy\u003c/code\u003e. You can change it to any other value if you like.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe namespace for the policy. It must be the same namespace the \u003ccode\u003eGateway\u003c/code\u003e resource and heimdall are deployed into. So change it to your namespace.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eDefines the \u003ccode\u003eGateway\u003c/code\u003e resource, this policy should be applied to. Change the \u003ccode\u003ename\u003c/code\u003e property to the name of your \u003ccode\u003eGateway\u003c/code\u003e resource and the \u003ccode\u003enamespace\u003c/code\u003e property to the proper namespace (same as in 2)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eDefines the reference to the heimdall \u003ccode\u003eService\u003c/code\u003e using the gRPC protocol. Change the \u003ccode\u003ename\u003c/code\u003e and the \u003ccode\u003enamespace\u003c/code\u003e to the proper values of your setup.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_route_level_configuration\"\u003eRoute-level Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe integration on the route level happens similar to the \u003ca href=\"#_global_configuration\"\u003eglobal integration\u003c/a\u003e. The difference is that the \u003ca href=\"https://gateway.envoyproxy.io/contributions/design/security-policy/\"\u003e\u003ccode\u003eSecurityPolicy\u003c/code\u003e\u003c/a\u003e is applied to an \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/httproute\"\u003e\u003ccode\u003eHTTPRoute\u003c/code\u003e\u003c/a\u003e as shown below and not the \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e resource.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egateway.envoyproxy.io/v1alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSecurityPolicy\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eext-auth-example\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etargetRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003egroup\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egateway.networking.k8s.io\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eHTTPRoute\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eextAuth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egrpc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebackendRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4455\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe name of the \u003ccode\u003eSecurityPolicy\u003c/code\u003e. You can change it to any other value if you like.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe namespace for the policy. It must be the same namespace the \u003ccode\u003eHTTPRoute\u003c/code\u003e resource is deployed into, so the namespace, your application is deployed to. So change it to your namespace.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eDefines the \u003ccode\u003eHTTPRoute\u003c/code\u003e resource, this policy should be applied to. Change the \u003ccode\u003ename\u003c/code\u003e property to the name of your \u003ccode\u003eHTTPRoute\u003c/code\u003e resource and the \u003ccode\u003enamespace\u003c/code\u003e property to the proper namespace (same as in 2)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eDefines the reference to the heimdall \u003ccode\u003eService\u003c/code\u003e using the gRPC protocol. Change the \u003ccode\u003ename\u003c/code\u003e and the \u003ccode\u003enamespace\u003c/code\u003e to the proper values of your setup.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_security_considerations\"\u003eSecurity Considerations\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration options shown above are highly insecure, as the communication from the gateway to heimdall happens over plain HTTP. Therefore, it is highly recommended to enable TLS. This can be achieved by enabling TLS for heimdall and attaching a \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy/\"\u003e\u003ccode\u003eBackendTLSPolicy\u003c/code\u003e\u003c/a\u003e resource shown below to heimdall’s \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/service/\"\u003e\u003ccode\u003eService\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egateway.networking.k8s.io/v1alpha2\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBackendTLSPolicy\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-btls\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etargetRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003egroup\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eService\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003esectionName\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e4455\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ecaCertRefs\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo-ca\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003egroup\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eConfigMap\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehostname\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eChange it to the namespace in which heimdall is deployed\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe reference to heimdall’s \u003ccode\u003eService\u003c/code\u003e. Change the \u003ccode\u003ename\u003c/code\u003e and the \u003ccode\u003enamespace\u003c/code\u003e to the proper values.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we configure the reference to the \u003ccode\u003eConfigMap\u003c/code\u003e with the certificate of the CA, used to issue a TLS server authentication certificate for heimdall, as well as the hostname used by heimdall (and present in the SAN extension of heimdall’s TLS certificate). The \u003ccode\u003eConfigMap\u003c/code\u003e must be in the same namespace as the \u003ccode\u003eBackendTLSPolicy\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe name of the \u003ccode\u003eConfigMap\u003c/code\u003e. Change it to the proper value.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe expected hostname used by heimdall. Change it to the proper value.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eA fully working example with Envoy Gateway is also available on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eYou can find the official external authentication guide for Envoy Gateway \u003ca href=\"https://gateway.envoyproxy.io/v1.0.1/tasks/security/ext-auth/\"\u003ehere\u003c/a\u003e. It contains a fully working setup with a demo application.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://gateway.envoyproxy.io/v1.0.1/tasks/security/secure-gateways/\"\u003eSecure Gateways\u003c/a\u003e is a highly recommended read as well.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Envoy Gateway Integration","url":"/guides/proxies/envoy_gateway/"},{"categories":null,"content":" Decision Mode In this mode you can integrate heimdall with existing reverse proxies, or API gateways (like Kong, NGNIX, Envoy, Traefik and much more)\nFigure 1. Decision Deployment In this mode heimdall can be integrated with most probably all modern API gateways and reverse proxies as a so-called \u0026#34;authentication middleware\u0026#34;. Here the reverse proxy, respectively API gateway integrating with heimdall, will forward requests to heimdall by making use of its main service endpoint for authentication and authorization purposes. As in the Reverse Proxy mode, heimdall will check if these requests match and satisfy the conditions defined in the available rules. If not, heimdall returns an error to its client (here API gateway/reverse proxy). If the rule execution was successful, it also responds to the API gateway/reverse proxy with 200 OK (can be overridden if required) and sets headers/cookies, specified in the matched rule, which are then forwarded to the upstream service.\nStarting heimdall in this mode happens via the serve decision command. Head over to the description of CLI as well as to corresponding configuration options for more details.\nExample 1. Decision Service Example Imagine following request hits heimdall (sent to it by an API gateway)\nGET /my-service/api HTTP/1.1 Host: heimdall:4455 X-Forwarded-Host: my-backend-service Some payload And there is a rule, which allows anonymous requests and sets a header with subject id set to anonymous like this\nid: rule:my-service:anonymous-api-access match: routes: - path: /my-service/api scheme: http hosts: - type: exact value: my-backend-service methods: - GET execute: - authenticator: anonymous-authn - finalizer: id-header Then heimdall will respond with:\nHTTP/1.1 200 OK X-User-ID: anonymous Proxy Mode In this operation mode you can use heimdall as a reverse proxy in front of your upstream API or web server.\nFigure 2. Proxy Deployment In this mode heimdall forwards requests to the upstream service if these satisfy the conditions defined in matched rules. Otherwise, heimdall returns an error to the client. If the execution of the rule was successful, it also forwards additional headers, specified in the rule to the upstream service.\nStarting heimdall in this mode happens via the serve proxy command. Head over to the description of CLI as well as to main service configuration options for more details.\nExample 2. Reverse Proxy Example Imagine following request hits heimdall\nGET /my-service/api HTTP/1.1 Host: heimdall:4455 Some payload And there is a rule, which allows anonymous requests and sets a header with subject id set to anonymous like this\nid: rule:my-service:anonymous-api-access match: routes: - path: /my-service/api methods: - GET forward_to: host: my-backend-service:8888 execute: - authenticator: anonymous-authn - finalizer: id-header Then the request will be forwarded as follows:\nGET /my-service/api HTTP/1.1 Host: my-backend-service:8888 X-User-ID: anonymous Some payload ","description":"To support different deployment scenarios, heimdall supports two operating modes.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_decision_mode\"\u003eDecision Mode\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this mode you can integrate heimdall with existing reverse proxies, or API gateways (like \u003ca href=\"https://konghq.com/\"\u003eKong\u003c/a\u003e, \u003ca href=\"https://nginx.org\"\u003eNGNIX\u003c/a\u003e, \u003ca href=\"https://www.envoyproxy.io/\"\u003eEnvoy\u003c/a\u003e, \u003ca href=\"https://traefik.io/\"\u003eTraefik\u003c/a\u003e and much more)\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_fig_heimdall_decision_deployment\" class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-6aa79a33899aaf938fd0bdc4e82460e2.svg\" alt=\"Diagram\" width=\"1020\" height=\"490\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 1. Decision Deployment\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this mode heimdall can be integrated with most probably all modern API gateways and reverse proxies as a so-called \u0026#34;authentication middleware\u0026#34;. Here the reverse proxy, respectively API gateway integrating with heimdall, will forward requests to heimdall by making use of its main service endpoint for authentication and authorization purposes. As in the \u003ca href=\"#_proxy_mode\"\u003eReverse Proxy\u003c/a\u003e mode, heimdall will check if these requests match and satisfy the conditions defined in the available rules. If not, heimdall returns an error to its client (here API gateway/reverse proxy). If the rule execution was successful, it also responds to the API gateway/reverse proxy with \u003ccode\u003e200 OK\u003c/code\u003e (can be overridden if required) and sets headers/cookies, specified in the matched rule, which are then forwarded to the upstream service.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eStarting heimdall in this mode happens via the \u003ccode\u003eserve decision\u003c/code\u003e command. Head over to the description of \u003ca href=\"/docs/operations/cli/\"\u003eCLI\u003c/a\u003e as well as to \u003ca href=\"/docs/services/main/\"\u003ecorresponding configuration options\u003c/a\u003e for more details.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Decision Service Example\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine following request hits heimdall (sent to it by an API gateway)\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eGET /my-service/api HTTP/1.1\nHost: heimdall:4455\nX-Forwarded-Host: my-backend-service\n\nSome payload\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAnd there is a rule, which allows anonymous requests and sets a header with subject id set to \u003ccode\u003eanonymous\u003c/code\u003e like this\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:my-service:anonymous-api-access\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/my-service/api\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-backend-service\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous-authn\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eid-header\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThen heimdall will respond with:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eHTTP/1.1 200 OK\nX-User-ID: anonymous\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_proxy_mode\"\u003eProxy Mode\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this operation mode you can use heimdall as a reverse proxy in front of your upstream API or web server.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_fig_heimdall_proxy_deployment\" class=\"imageblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cimg src=\"diag-ditaa-md5-bd38a9b34b3de344495c4271ed4b394a.svg\" alt=\"Diagram\" width=\"980\" height=\"308\"/\u003e\n\u003c/div\u003e\n\u003cdiv class=\"title\"\u003eFigure 2. Proxy Deployment\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this mode heimdall forwards requests to the upstream service if these satisfy the conditions defined in matched rules. Otherwise, heimdall returns an error to the client. If the execution of the rule was successful, it also forwards additional headers, specified in the rule to the upstream service.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eStarting heimdall in this mode happens via the \u003ccode\u003eserve proxy\u003c/code\u003e command. Head over to the description of \u003ca href=\"/docs/operations/cli/\"\u003eCLI\u003c/a\u003e as well as to \u003ca href=\"/docs/services/main/\"\u003emain service configuration options\u003c/a\u003e for more details.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Reverse Proxy Example\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine following request hits heimdall\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eGET /my-service/api HTTP/1.1\nHost: heimdall:4455\n\nSome payload\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAnd there is a rule, which allows anonymous requests and sets a header with subject id set to \u003ccode\u003eanonymous\u003c/code\u003e like this\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:my-service:anonymous-api-access\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/my-service/api\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n\u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-backend-service:8888\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous-authn\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eid-header\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThen the request will be forwarded as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eGET /my-service/api HTTP/1.1\nHost: my-backend-service:8888\nX-User-ID: anonymous\n\nSome payload\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Concepts"],"tags":null,"title":"Operating Modes","url":"/docs/concepts/operating_modes/"},{"categories":null,"content":" HAProxy (High Availability Proxy) is a popular open source, fast, and reliable solution providing load balancer and reverse proxy features for TCP- and HTTP-based applications, capable handling heavy load traffic and rerouting requests seamlessly across multiple workloads (e.g. web, application, database).\nVanilla HAProxy HAProxy is highly extensible thanks to Lua scripting support. For that reason the vanilla HAProxy does not implement any means of external authorization support and requires custom Lua code to achieve integration with heimdall.\nHAProxy Ingress Controller The HAProxy Ingress Controller has the required integration options however in place. That way, delegation of authentication and authorization to heimdall operated in Decision Mode is easily possible using the Ingress rule annotations as well as globally, with latter allowing implementation of secure defaults for all your workloads\nIn both cases, if heimdall answers with a 2XX code, HAProxy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\nThis integration requires proper configuration of trusted_proxies. Global integration There seems to be a bug in the implementation of the HAProxy Ingress controller. Even the below description is based on the official documentation, it does not work. Corresponding ticket has been filed: https://github.com/jcmoraisjr/haproxy-ingress/issues/1105. Please check the status of this ticket first. To have the integration configured globally and used for all workloads, you have to add the keys shown in the snipped below to the data of the ConfigMap used by the haproxy ingress controller.\napiVersion: v1 kind: ConfigMap data: auth-url: \u0026#34;https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34; (1) auth-headers-succeed: \u0026#34;authorization\u0026#34; (2) headers: | (3) X-Forwarded-Uri: %[pathq] X-Forwarded-Method: %[method] X-Forwarded-Host: %[req.hdr(host)] 1 Configures the controller to use heimdall’s main service endpoint with \u0026lt;heimdall service name\u0026gt;, \u0026lt;namespace\u0026gt; and \u0026lt;port\u0026gt; depending on your configuration. 2 Let HAProxy forward the Authorization header set by heimdall to the upstream service upon successful response. This configuration depends on your Contextualizers and Finalizers configuration. There is currently a limitation in HAProxy Ingress Controller regarding the case-insensitivity for headers. Since heimdall returns the header in lower-case, it is important to set the names of the required to be forwarded headers in lower case as well. 3 Configures the required headers to pass the information about the used HTTP scheme, host and port, request path and used query parameters to be forwarded to heimdall. X-Forwarded-Proto is not used, as it is already set by HAProxy by default. If the installation of haproxy ingress controller happens using helm, these keys can easily be added by making use of the controller.config property (see also Helm chart configuration options for details).\nIngress Rule based integration The code snipped below shows the required annotations on the ingress rule. It uses the same configuration keys as the global configuration prefixed with haproxy-ingress.github.io/\nannotations: haproxy-ingress.github.io/auth-url: \u0026#34;https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34; haproxy-ingress.github.io/auth-headers-succeed: \u0026#34;authorization\u0026#34; haproxy-ingress.github.io/headers: | X-Forwarded-Uri: %[pathq] X-Forwarded-Method: %[method] X-Forwarded-Host: %[req.hdr(host)] Additional Resources Checkout the examples on GitHub for a working demo.\n","description":"Explains how to integrate heimdall with HAProxy.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://www.haproxy.com/\"\u003eHAProxy\u003c/a\u003e (High Availability Proxy) is a popular open source, fast, and reliable solution providing load balancer and reverse proxy features for TCP- and HTTP-based applications, capable handling heavy load traffic and rerouting requests seamlessly across multiple workloads (e.g. web, application, database).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_vanilla_haproxy\"\u003eVanilla HAProxy\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHAProxy is highly extensible thanks to Lua scripting support. For that reason the vanilla HAProxy does not implement any means of external authorization support and requires custom Lua code to achieve integration with heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_haproxy_ingress_controller\"\u003eHAProxy Ingress Controller\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"https://haproxy-ingress.github.io/\"\u003eHAProxy Ingress Controller\u003c/a\u003e has the required \u003ca href=\"https://haproxy-ingress.github.io/docs/configuration/keys/#auth-external\"\u003eintegration options\u003c/a\u003e however in place. That way, delegation of authentication and authorization to heimdall operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Mode\u003c/a\u003e is easily possible using the Ingress rule annotations as well as globally, with latter allowing implementation of secure defaults for all your workloads\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both cases, if heimdall answers with a 2XX code, HAProxy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis integration requires proper configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_global_integration\"\u003eGlobal integration\u003c/h3\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThere seems to be a bug in the implementation of the HAProxy Ingress controller. Even the below description is based on the official documentation, it does not work. Corresponding ticket has been filed: \u003ca href=\"https://github.com/jcmoraisjr/haproxy-ingress/issues/1105\" class=\"bare\"\u003ehttps://github.com/jcmoraisjr/haproxy-ingress/issues/1105\u003c/a\u003e. Please check the status of this ticket first.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo have the integration configured globally and used for all workloads, you have to add the keys shown in the snipped below to the \u003ccode\u003edata\u003c/code\u003e of the \u003ca href=\"https://haproxy-ingress.github.io/docs/configuration/keys/#configmap\"\u003eConfigMap\u003c/a\u003e used by the haproxy ingress controller.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ev1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eConfigMap\u003c/span\u003e\n\u003cspan class=\"na\"\u003edata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth-url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://\u0026lt;heimdall\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eservice\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eauth-headers-succeed\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eauthorization\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Uri: %[pathq]\u003c/span\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Method: %[method]\u003c/span\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Host: %[req.hdr(host)]\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures the controller to use heimdall’s main service endpoint with \u003ccode\u003e\u0026lt;heimdall service name\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;namespace\u0026gt;\u003c/code\u003e and \u003ccode\u003e\u0026lt;port\u0026gt;\u003c/code\u003e depending on your configuration.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet HAProxy forward the \u003ccode\u003eAuthorization\u003c/code\u003e header set by heimdall to the upstream service upon successful response. This configuration depends on\nyour \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThere is currently a limitation in HAProxy Ingress Controller regarding the case-insensitivity for headers. Since heimdall returns the header in lower-case, it is important to set the names of the required to be forwarded headers in lower case as well.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures the required headers to pass the information about the used HTTP scheme, host and port, request path and used query parameters to be forwarded to heimdall. \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e is not used, as it is already set by HAProxy by default.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the installation of haproxy ingress controller happens using helm, these keys can easily be added by making use of the \u003ccode\u003econtroller.config\u003c/code\u003e property (see also \u003ca href=\"https://github.com/haproxy-ingress/charts/blob/release-0.14/haproxy-ingress/README.md#configuration\"\u003eHelm chart configuration options\u003c/a\u003e for details).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_ingress_rule_based_integration\"\u003eIngress Rule based integration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe code snipped below shows the required annotations on the ingress rule. It uses the same configuration keys as the global configuration prefixed with \u003ccode\u003ehaproxy-ingress.github.io/\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eannotations\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehaproxy-ingress.github.io/auth-url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://\u0026lt;heimdall\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eservice\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehaproxy-ingress.github.io/auth-headers-succeed\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eauthorization\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehaproxy-ingress.github.io/headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Uri: %[pathq]\u003c/span\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Method: %[method]\u003c/span\u003e\n \u003cspan class=\"s\"\u003eX-Forwarded-Host: %[req.hdr(host)]\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCheckout the examples on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e for a working demo.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"HAProxy Integration","url":"/guides/proxies/haproxy/"},{"categories":null,"content":" Istio is an open-source service mesh that extends Kubernetes’ capabilities, providing a uniform way to observe, secure, and connect microservices. It also functions as a Kubernetes-based application gateway, using either its built-in Ingress Gateway, the Kubernetes Ingress, or the Gateway API resources for configuration.\nPrerequisites A kubernetes cluster\nDeployed Istio (See here for installation options)\nheimdall installed and operated in Decision Operation Mode.\nTo allow heimdall communicating with services running in the mesh, add the certificate of the CA used by Istio to heimdall’s trust store. Integration Options Technically, the integration works similarly to the Envoy setup by utilizing the External Authorization filter. This can be implemented in two ways:\nvia HTTP\nvia gRPC (recommended)\nIn both approaches, the filter sends a request to an external gRPC or HTTP service (in this case, heimdall) to determine if the incoming HTTP request is authorized. If heimdall responds with a 2xx status code, the request is forwarded to the upstream service. Otherwise, heimdall’s response is returned to the caller.\nFor Istio, this integration involves configuring an envoyExtAuthzHttp or envoyExtAuthzGrpc ExtensionProvider for heimdall in the mesh configuration. The configured extension can then be enabled via an AuthorizationPolicy resource. Depending on its definition, heimdall can be used globally for all requests served through a particular gateway, or selectively for specific requests only.\nThe sections below explain how to achieve this for Istio’s Ingress Gateway, as well as using the Kubernetes Gateway API.\nThis guide assumes that Istio and heimdall are installed in the same cluster. If they are not, you will need to register heimdall in Istio’s internal service registry using a ServiceEntry resource. Common Configuration Register the Extension Provider As mentioned earlier, registering an extension provider in Istio’s mesh configuration is required. Follow these steps:\nEdit the mesh configuration: Run kubectl edit configmap istio -n istio-system to open the mesh configuration for editing.\nAdd the extensionProvider configuration: Insert the following settings into the mesh configuration:\napiVersion: v1 data: mesh: |- # Add the following contents: extensionProviders: - name: heimdall-ext-auth (1) envoyExtAuthzGrpc: (2) service: heimdall.heimdall.svc.cluster.local (3) port: \u0026#34;4455\u0026#34; 1 heimdall-ext-auth is the name of our extension provider, which will be referenced later in the AuthorizationPolicy configuration. 2 We’re using a gRPC based implementation here. However, since Istio does not automatically configure Envoy to use HTTP/2 for gRPC calls, it requires an additional EnvoyFilter resource. This appears to be a bug in Istio’s implementation. 3 Heimdall’s address within the cluster, which the extension provider will use for communication. Alternatively, you can make use of envoyExtAuthzHttp extension provider. In that case insert the following settings:\napiVersion: v1 data: mesh: |- # Add the following contents: extensionProviders: - name: heimdall-ext-auth envoyExtAuthzHttp: service: heimdall.heimdall.svc.cluster.local port: \u0026#34;4455\u0026#34; includeRequestHeadersInCheck: [ \u0026#34;authorization\u0026#34;, \u0026#34;cookie\u0026#34;, \u0026#34;accept\u0026#34;, \u0026#34;x-forwarded-for\u0026#34;, \u0026#34;x-forwarded-proto\u0026#34;, \u0026#34;x-forwarded-host\u0026#34; ] (1) headersToUpstreamOnAllow: [ \u0026#34;authorization\u0026#34; ] (2) 1 Include further headers, you expect to make use of in your heimdall rules. 2 Include further headers, you expect to be set in your heimdall rules and which should be forwarded to the upstream service. Deploy the following EnvoyFilter resource to correct the cluster configuration that Istio sets up for the heimdall service.\nThis is only required if you made use of the envoyExtAuthzGrpc provider as shown above. apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: http2-protocol-for-heimdall namespace: istio-system (1) spec: configPatches: - applyTo: CLUSTER (2) match: (3) context: GATEWAY cluster: name: outbound|4455||heimdall.heimdall.svc.cluster.local patch: operation: MERGE value: typed_extension_protocol_options: (4) envoy.extensions.upstreams.http.v3.HttpProtocolOptions: \u0026#34;@type\u0026#34;: type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicit_http_config: http2_protocol_options: {} 1 The namespace where the Istio control plane is deployed (the config root namespace). That way this filter is used each time envoy instance is created by Istio. 2 Specifies that we want to apply the patch for a cluster 3 Since we want this patch to be applied for gateways only, we limit the context accordingly 4 This is the actual config we would like to merge into the cluster definition to enable HTTP/2 support. Configure additional CA certificates This step is optional and only necessary if heimdall is configured to use TLS for inbound traffic.\nIt is highly recommended to secure the communication between the Istio-managed gateway and heimdall. Instead of configuring heimdall to handle TLS directly, you can let Istio inject a proxy into heimdall’s pod to manage TLS termination. However, this approach introduces an additional network hop, which could negatively impact performance. Instruct Istio to trust heimdall’s certificate by applying the following DestinationRule resource in the Istio root configuration namespace:\napiVersion: networking.istio.io/v1 kind: DestinationRule metadata: name: heimdall namespace: istio-system spec: host: heimdall.heimdall.svc.cluster.local trafficPolicy: tls: mode: SIMPLE sni: heimdall.heimdall.svc.cluster.local (1) credentialName: cacerts (2) 1 If sni is not set, it defaults to the downstream HTTP Host or Authority header, which will cause an error on the heimdall side because the name will not match the DNS entries in heimdall’s certificate. 2 The secret contains the certificate of the CA that issued heimdall’s certificate. Without this, Envoy won’t trust heimdall’s certificate. This secret must be available in every namespace where Istio creates a gateway. Route the requests through heimdall With the previous configuration in place, we can now instruct Istio to route the ingress traffic through heimdall first.\nCreate the following AuthorizationPolicy in Istio’s root configuration namespace:\napiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: heimdall namespace: istio-system spec: selector: matchLabels: (1) istio: ingressgateway action: CUSTOM provider: name: heimdall-ext-auth (2) rules: - {} (3) 1 This policy is specifically intended for gateways, excluding injected sidecars. 2 Here, we reference the extension provider that was configured earlier. 3 The policy is set to apply universally, with no specific conditions, hence the empty rules. With this configuration completed, you can proceed to deploy the necessary gateway resources.\nIngress Gateway Configuration Simply create the Ingress Gateway resource and define the VirtualService resources for your services according to your requirements. No further configuration is necessary.\nKubenetes Gateway API As of this writing, Istio’s implementation of the Gateway API appears incomplete. It lacks the necessary Role and RoleBinding to access the Secret containing additional CA certificates. Without these, the Envoy instances cannot access the secret, preventing them from trusting heimdall’s certificate. To resolve this, apply the following resources in the namespace where the Gateway will be installed:\napiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: gateway.istio.io/managed: istio.io-gateway-controller gateway.networking.k8s.io/gateway-name: istio-gw istio: ingressgateway istio.io/gateway-name: istio-gw name: istio-gw-istio namespace: istio-gw rules: - apiGroups: - \u0026#34;\u0026#34; resources: - secrets verbs: - get - watch - list --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: gateway.istio.io/managed: istio.io-gateway-controller gateway.networking.k8s.io/gateway-name: istio-gw istio: ingressgateway istio.io/gateway-name: istio-gw name: istio-gw-istio namespace: istio-gw roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: istio-gw-istio subjects: - kind: ServiceAccount name: istio-gw-istio (1) 1 Change the name of the service account accordingly; it follows the pattern \u0026lt;namespace\u0026gt;-istio. Now, you can create the required Gateway and HTTPRoute resources for your service. When creating the Gateway resource, ensure you add the istio: ingressgateway label to its metadata. If you omit this label, the AuthorizationPolicy configured earlier will not be applied.\nAdditional Resources A fully working example with Istio is also available on GitHub.\n","description":"Explains how to integrate heimdall with Istio Service Mesh.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://istio.io/\"\u003eIstio\u003c/a\u003e is an open-source service mesh that extends Kubernetes’ capabilities, providing a uniform way to observe, secure, and connect microservices. It also functions as a Kubernetes-based application gateway, using either its built-in \u003ca href=\"https://istio.io/latest/docs/concepts/traffic-management/#gateways\"\u003eIngress Gateway\u003c/a\u003e, the Kubernetes \u003ca href=\"https://istio.io/latest/docs/tasks/traffic-management/ingress/kubernetes-ingress/\"\u003eIngress\u003c/a\u003e, or the \u003ca href=\"https://gateway-api.sigs.k8s.io/\"\u003eGateway API\u003c/a\u003e resources for configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eA kubernetes cluster\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDeployed Istio (See \u003ca href=\"https://istio.io/latest/docs/setup/install/\"\u003ehere\u003c/a\u003e for installation options)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eheimdall installed and operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nTo allow heimdall communicating with services running in the mesh, add the certificate of the CA used by Istio to heimdall’s \u003ca href=\"/docs/operations/security/#_tls_trust_store\"\u003etrust store\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_integration_options\"\u003eIntegration Options\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTechnically, the integration works similarly to the \u003ca href=\"/guides/proxies/envoy/\"\u003eEnvoy\u003c/a\u003e setup by utilizing the \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html\"\u003eExternal Authorization\u003c/a\u003e filter. This can be implemented in two ways:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003evia HTTP\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003evia gRPC (recommended)\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn both approaches, the filter sends a request to an external gRPC or HTTP service (in this case, heimdall) to determine if the incoming HTTP request is authorized. If heimdall responds with a \u003ccode\u003e2xx\u003c/code\u003e status code, the request is forwarded to the upstream service. Otherwise, heimdall’s response is returned to the caller.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor Istio, this integration involves configuring an \u003ccode\u003eenvoyExtAuthzHttp\u003c/code\u003e or \u003ccode\u003eenvoyExtAuthzGrpc\u003c/code\u003e \u003ca href=\"https://istio.io/latest/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig-ExtensionProvider\"\u003eExtensionProvider\u003c/a\u003e for heimdall in the mesh configuration. The configured extension can then be enabled via an \u003ca href=\"https://istio.io/latest/docs/reference/config/security/authorization-policy/\"\u003e\u003ccode\u003eAuthorizationPolicy\u003c/code\u003e\u003c/a\u003e resource. Depending on its definition, heimdall can be used globally for all requests served through a particular gateway, or selectively for specific requests only.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe sections below explain how to achieve this for Istio’s Ingress Gateway, as well as using the Kubernetes Gateway API.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis guide assumes that Istio and heimdall are installed in the same cluster. If they are not, you will need to register heimdall in Istio’s internal service registry using a \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/service-entry/\"\u003e\u003ccode\u003eServiceEntry\u003c/code\u003e\u003c/a\u003e resource.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_common_configuration\"\u003eCommon Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_register_the_extension_provider\"\u003eRegister the Extension Provider\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs mentioned earlier, registering an extension provider in Istio’s mesh configuration is required. Follow these steps:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eEdit the mesh configuration: Run \u003ccode\u003ekubectl edit configmap istio -n istio-system\u003c/code\u003e to open the mesh configuration for editing.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAdd the \u003ccode\u003eextensionProvider\u003c/code\u003e configuration: Insert the following settings into the mesh configuration:\u003c/p\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ev1\u003c/span\u003e\n\u003cspan class=\"na\"\u003edata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emesh\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|-\u003c/span\u003e\n \u003cspan class=\"s\"\u003e# Add the following contents:\u003c/span\u003e\n \u003cspan class=\"s\"\u003eextensionProviders:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e- name: heimdall-ext-auth \u003c/span\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eenvoyExtAuthzGrpc: \u003c/span\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eservice: heimdall.heimdall.svc.cluster.local \u003c/span\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eport: \u0026#34;4455\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eheimdall-ext-auth\u003c/code\u003e is the name of our extension provider, which will be referenced later in the \u003ca href=\"https://istio.io/latest/docs/reference/config/security/authorization-policy/\"\u003e\u003ccode\u003eAuthorizationPolicy\u003c/code\u003e\u003c/a\u003e configuration.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWe’re using a gRPC based implementation here. However, since Istio does not automatically configure Envoy to use HTTP/2 for gRPC calls, it requires an additional \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/envoy-filter/\"\u003e\u003ccode\u003eEnvoyFilter\u003c/code\u003e\u003c/a\u003e resource. This appears to be a bug in Istio’s implementation.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHeimdall’s address within the cluster, which the extension provider will use for communication.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAlternatively, you can make use of \u003ccode\u003eenvoyExtAuthzHttp\u003c/code\u003e extension provider. In that case insert the following settings:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ev1\u003c/span\u003e\n\u003cspan class=\"na\"\u003edata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emesh\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|-\u003c/span\u003e\n \u003cspan class=\"s\"\u003e# Add the following contents:\u003c/span\u003e\n \u003cspan class=\"s\"\u003eextensionProviders:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e- name: heimdall-ext-auth\u003c/span\u003e\n \u003cspan class=\"s\"\u003eenvoyExtAuthzHttp:\u003c/span\u003e\n \u003cspan class=\"s\"\u003eservice: heimdall.heimdall.svc.cluster.local\u003c/span\u003e\n \u003cspan class=\"s\"\u003eport: \u0026#34;4455\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eincludeRequestHeadersInCheck: [ \u0026#34;authorization\u0026#34;, \u0026#34;cookie\u0026#34;, \u0026#34;accept\u0026#34;, \u0026#34;x-forwarded-for\u0026#34;, \u0026#34;x-forwarded-proto\u0026#34;, \u0026#34;x-forwarded-host\u0026#34; ] \u003c/span\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eheadersToUpstreamOnAllow: [ \u0026#34;authorization\u0026#34; ] \u003c/span\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eInclude further headers, you expect to make use of in your heimdall rules.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eInclude further headers, you expect to be set in your heimdall rules and which should be forwarded to the upstream service.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDeploy the following \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/envoy-filter/\"\u003e\u003ccode\u003eEnvoyFilter\u003c/code\u003e\u003c/a\u003e resource to correct the cluster configuration that Istio sets up for the heimdall service.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis is only required if you made use of the \u003ccode\u003eenvoyExtAuthzGrpc\u003c/code\u003e provider as shown above.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enetworking.istio.io/v1alpha3\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eEnvoyFilter\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp2-protocol-for-heimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-system\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfigPatches\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eapplyTo\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eCLUSTER\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003econtext\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGATEWAY\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecluster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoutbound|4455||heimdall.heimdall.svc.cluster.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003epatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eoperation\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eMERGE\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etyped_extension_protocol_options\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eenvoy.extensions.upstreams.http.v3.HttpProtocolOptions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@type\u0026#34;\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etype.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions\u003c/span\u003e\n \u003cspan class=\"s\"\u003eexplicit_http_config\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp2_protocol_options\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe namespace where the Istio control plane is deployed (the config root namespace). That way this filter is used each time envoy instance is created by Istio.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSpecifies that we want to apply the patch for a cluster\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSince we want this patch to be applied for gateways only, we limit the context accordingly\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is the actual config we would like to merge into the cluster definition to enable HTTP/2 support.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configure_additional_ca_certificates\"\u003eConfigure additional CA certificates\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis step is optional and only necessary if heimdall is configured to use TLS for inbound traffic.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIt is highly recommended to secure the communication between the Istio-managed gateway and heimdall. Instead of configuring heimdall to handle TLS directly, you can let Istio inject a proxy into heimdall’s pod to manage TLS termination. However, this approach introduces an additional network hop, which could negatively impact performance.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eInstruct Istio to trust heimdall’s certificate by applying the following \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/destination-rule/\"\u003e\u003ccode\u003eDestinationRule\u003c/code\u003e\u003c/a\u003e resource in the Istio root configuration namespace:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enetworking.istio.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eDestinationRule\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-system\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall.heimdall.svc.cluster.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003etrafficPolicy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSIMPLE\u003c/span\u003e\n \u003cspan class=\"na\"\u003esni\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall.heimdall.svc.cluster.local\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ecredentialName\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecacerts\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eIf \u003ccode\u003esni\u003c/code\u003e is not set, it defaults to the downstream HTTP \u003ccode\u003eHost\u003c/code\u003e or \u003ccode\u003eAuthority\u003c/code\u003e header, which will cause an error on the heimdall side because the name will not match the DNS entries in heimdall’s certificate.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe secret contains the certificate of the CA that issued heimdall’s certificate. Without this, Envoy won’t trust heimdall’s certificate. This secret must be available in every namespace where Istio creates a gateway.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_route_the_requests_through_heimdall\"\u003eRoute the requests through heimdall\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith the previous configuration in place, we can now instruct Istio to route the ingress traffic through heimdall first.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eCreate the following \u003ca href=\"https://istio.io/latest/docs/reference/config/security/authorization-policy/\"\u003e\u003ccode\u003eAuthorizationPolicy\u003c/code\u003e\u003c/a\u003e in Istio’s root configuration namespace:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esecurity.istio.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorizationPolicy\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-system\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eselector\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematchLabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eistio\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eingressgateway\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaction\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eCUSTOM\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprovider\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-ext-auth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis policy is specifically intended for gateways, excluding injected sidecars.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we reference the extension provider that was configured earlier.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe policy is set to apply universally, with no specific conditions, hence the empty rules.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith this configuration completed, you can proceed to deploy the necessary gateway resources.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_ingress_gateway_configuration\"\u003eIngress Gateway Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSimply create the Ingress \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/gateway/\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e resource and define the \u003ca href=\"https://istio.io/latest/docs/reference/config/networking/virtual-service/\"\u003e\u003ccode\u003eVirtualService\u003c/code\u003e\u003c/a\u003e resources for your services according to your requirements. No further configuration is necessary.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_kubenetes_gateway_api\"\u003eKubenetes Gateway API\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs of this writing, Istio’s implementation of the Gateway API appears incomplete. It lacks the necessary \u003ccode\u003eRole\u003c/code\u003e and \u003ccode\u003eRoleBinding\u003c/code\u003e to access the \u003ccode\u003eSecret\u003c/code\u003e containing additional CA certificates. Without these, the Envoy instances cannot access the secret, preventing them from trusting heimdall’s certificate. To resolve this, apply the following resources in the namespace where the \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/gateway/#api-kind-gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e will be installed:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erbac.authorization.k8s.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRole\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egateway.istio.io/managed\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio.io-gateway-controller\u003c/span\u003e\n \u003cspan class=\"na\"\u003egateway.networking.k8s.io/gateway-name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n \u003cspan class=\"na\"\u003eistio\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eingressgateway\u003c/span\u003e\n \u003cspan class=\"na\"\u003eistio.io/gateway-name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw-istio\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eapiGroups\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eresources\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003esecrets\u003c/span\u003e\n \u003cspan class=\"na\"\u003everbs\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eget\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ewatch\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003elist\u003c/span\u003e\n\u003cspan class=\"nn\"\u003e---\u003c/span\u003e\n\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erbac.authorization.k8s.io/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRoleBinding\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egateway.istio.io/managed\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio.io-gateway-controller\u003c/span\u003e\n \u003cspan class=\"na\"\u003egateway.networking.k8s.io/gateway-name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n \u003cspan class=\"na\"\u003eistio\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eingressgateway\u003c/span\u003e\n \u003cspan class=\"na\"\u003eistio.io/gateway-name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw-istio\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw\u003c/span\u003e\n\u003cspan class=\"na\"\u003eroleRef\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eapiGroup\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erbac.authorization.k8s.io\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRole\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw-istio\u003c/span\u003e\n\u003cspan class=\"na\"\u003esubjects\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eServiceAccount\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eistio-gw-istio\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eChange the name of the service account accordingly; it follows the pattern \u003ccode\u003e\u0026lt;namespace\u0026gt;-istio\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNow, you can create the required \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/gateway/#api-kind-gateway\"\u003e\u003ccode\u003eGateway\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/gateway/#api-kind-httproute\"\u003e\u003ccode\u003eHTTPRoute\u003c/code\u003e\u003c/a\u003e resources for your service. When creating the \u003ccode\u003eGateway\u003c/code\u003e resource, ensure you add the \u003ccode\u003eistio: ingressgateway\u003c/code\u003e label to its metadata. If you omit this label, the \u003ca href=\"https://istio.io/latest/docs/reference/config/security/authorization-policy/\"\u003e\u003ccode\u003eAuthorizationPolicy\u003c/code\u003e\u003c/a\u003e configured earlier will not be applied.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA fully working example with Istio is also available on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Istio Service Mesh Integration","url":"/guides/proxies/istio/"},{"categories":null,"content":" NGINX is an HTTP and reverse proxy server which became famous as one of the fastest web servers out there, heimdall can be integrated with by making use of the ngx_http_auth_request_module. In such setup, NGINX delegates authentication and authorization to heimdall. If heimdall answers with a 2XX code, NGINX grants access and forwards the original request to the upstream service. If heimdall returns 401 or 403, the access is denied with the corresponding error code. Any other response code returned by heimdall is considered an error.\nPrerequisites Integration with NGINX requires heimdall being operated in Decision Operation Mode exposing its HTTP(s) endpoint.\nLimitations NGINX ngx_http_auth_request_module responsible for communication with external authentication \u0026amp; authorization services, like heimdall, has a few limitations. As written above, it only supports 200, 401 and 403 response codes. That means:\nYou’ll not be able to drive redirects from heimdall, as 3xx error codes will result in 500 error returned by NGINX. You can partially overcome that limitation by letting heimdall respond with a 401 or 403 error code and mapping that to a redirect in NGINX itself, e.g. like shown below. This definitely not DRY and will not allow you using multiple identity provider if you need to\n# nginx.conf ... # if the ext auth server, like heimdall returns `401 not authorized` # then forward the request to the error401 block error_page 401 = @error401; location @error401 { # redirect to the IdP for login return 302 https://your-idp-service/login; # you usually want your IdP to redirect back upon successful authentication # typically, you can achieve that by adding such query parameters like # return_to set to the value of the current request } If there is no matching rule on heimdall side, heimdall responds with 404 Not Found, which, as said above will be treated by NGINX as error. To avoid such situations, you can define a default rule, which is anyway recommended to have secure defaults\nVanilla NGINX Since NGINX is highly configurable and heimdall supports different integration options, you can use any of the configuration examples given below. All of these enable heimdall to build the URL of the protected backend server for rule matching purposes.\nIn most cases you must configure heimdall to trust your NGINX instances by setting trusted_proxies. Exceptions are described in the sections below.\nForward only the path and query information With this method you don’t set any headers. That means, you cannot rely on the used HTTP scheme, or the host and port in your rules. Here NGINX uses the same HTTP method, used in the original request to it and add the path and query to the path/query URL used for communication with heimdall. That integration method does not require the configuration of trusted_proxies in heimdall.\n# nginx.conf ... location / { auth_request /_auth; (1) auth_request_set $auth_cookie $upstream_http_set_cookie; (2) add_header Set-Cookie $auth_cookie; auth_request_set $authHeader0 $upstream_http_authorization; (3) proxy_set_header \u0026#39;Authorization\u0026#39; $authHeader0; # mitigate HTTPoxy Vulnerability # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ proxy_set_header Proxy \u0026#34;\u0026#34;; ... } location = /_auth { (4) internal; access_log off; proxy_method $request_method; (5) proxy_pass https://heimdall:4455$request_uri; (6) proxy_pass_request_body off; (7) proxy_set_header Content-Length \u0026#34;\u0026#34;; proxy_set_header Host $http_host; (8) } 1 Configures NGINX to forward every request to the internal /_auth endpoint (this is where the actual heimdall integration happens - see below). 2 When the response from heimdall returns, this and the next line set the Cookies set by heimdall in the response (whether you need this depends on your Contextualizers and Finalizers configuration) 3 When the response from heimdall returns, this and the next line set the Authorization header set by heimdall in the response (which header to set depends again on your Contextualizers and Finalizers configuration) 4 This is where the \u0026#34;magic\u0026#34; happens 5 Configure NGINX to use the HTTP method used by its client. Without this setting the implementation of proxy_path will use the HTTP GET method. 6 Configures NGINX to pass the request to heimdall and sets the request path and queries from the original request 7 Disables sending of the request body. If your heimdall rules make use of the body, you should set this to on and remove the next line. 8 Lets the NGINX setting the Host header, so it is accessible to heimdall. Forward all information in X-Forwarded-* headers With this method you set the X-Forwarded-Method, X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-Uri to let heimdall know the host, respectively domain url and the used HTTP method.\nCompared to the previous integration option, the configuration only differs in the definition of the internal /_auth endpoint. So, the example configuration is limited to that part only.\nProper configuration of trusted_proxies is mandatory if using this option. # nginx.conf ... location = /_auth { internal; proxy_pass https://heimdall:4455; (1) proxy_pass_request_body off; proxy_set_header Content-Length \u0026#34;\u0026#34;; proxy_set_header X-Forwarded-Method $request_method; (2) proxy_set_header X-Forwarded-Proto $scheme; (3) proxy_set_header X-Forwarded-Host $http_host; (4) proxy_set_header X-Forwarded-Uri $request_uri; (5) proxy_set_header X-Forwarded-For $remote_addr; } 1 Configures NGINX to pass the request to heimdall. 2 Let NGINX forward the used HTTP method to heimdall. 3 Let NGINX forward the used HTTP scheme to heimdall. 4 Let NGINX forward the used host to heimdall. 5 Let NGINX forward the used path and query parameter to heimdall. NGINX Ingress Controller Global Configuration Using X-Forwarded-* headers The configuration used in the example below requires proper configuration of trusted_proxies on heimdall side. Global configuration can be achieved by setting the following properties in controller ConfigMap. If you install the NGINX controller via the helm chart, you can add these properties under the controller.config property of your helm values.yaml file.\nglobal-auth-url: \u0026#34;https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34; (1) global-auth-response-headers: Authorization (2) global-auth-snippet: | (3) proxy_set_header X-Forwarded-Method $request_method; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-Uri $request_uri; 1 Configures the controller to use heimdall’s main service endpoint with \u0026lt;heimdall service name\u0026gt;, \u0026lt;namespace\u0026gt; and \u0026lt;port\u0026gt; depending on your configuration. 2 Let NGINX forward the Authorization header set by heimdall to the upstream service upon successful response. This configuration depends on your Contextualizers and Finalizers configuration. If not configured, NGINX will only react on Set-Cookie headers in responses from heimdall by default. 3 Configures the required headers to pass the information about the used HTTP scheme, host and port, request path and used query parameters to be forwarded to heimdall. Without that, heimdall will not be able extracting relevant information from the NGINX request as it does not support NGINX proprietary X-Original-Method and X-Original-Uri used by it for the same purposes. With that in place, you can simply use the standard Ingress resource, and the NGINX Ingress Controller will ensure, each request will be analyzed by heimdall first.\nThis will result in an NGINX configuration corresponding to the integration option, described in the Forward all information in X-Forwarded-* headers section.\nAlternative Configuration Alternatively, if you don’t want configuring trusted_proxies and do not rely on the used HTTP scheme, host and port in your rules, you can also use the location-snippet and the server-snippet to the ConfigMap of the NGINX Ingress Controller with values shown below.\nThis example is an exact copy of the configuration used in the very first integration option described above.\nlocation-snippet: | auth_request /_auth; auth_request_set $auth_cookie $upstream_http_set_cookie; add_header Set-Cookie $auth_cookie; auth_request_set $auth_header $upstream_http_authorization; proxy_set_header \u0026#39;Authorization\u0026#39; $auth_header; proxy_set_header Proxy \u0026#34;\u0026#34;; server-snippet: | location = /_auth { internal; access_log off; proxy_method $request_method; proxy_pass https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;$request_uri; proxy_pass_request_body off; proxy_set_header Content-Length \u0026#34;\u0026#34;; proxy_set_header Host $http_host; } As with the previous integration option, you can add these properties under the controller.config property of your helm values.yaml file if you install the NGINX Ingress Controller via helm.\nIntegration on Ingress Resource Level Using X-Forwarded-* headers One option to integrate heimdall with the NGINX Ingress Controller on the Ingress resource level is making use of the nginx.ingress.kubernetes.io/auth-url, nginx.ingress.kubernetes.io/auth-response-headers and the nginx.ingress.kubernetes.io/auth-snippet annotation as shown in the example below. This approach requires proper configuration of trusted_proxies on heimdall side. On NGINX Ingress Controller side you must allow the usage of nginx.ingress.kubernetes.io/auth-snippet (See also here).\nnginx.ingress.kubernetes.io/auth-url: \u0026#34;https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34; nginx.ingress.kubernetes.io/auth-response-headers: Authorization nginx.ingress.kubernetes.io/auth-snippet: | proxy_set_header X-Forwarded-Method $request_method; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-Uri $request_uri; # other annotations required Alternative Configuration Alternatively, if you don’t want configuring trusted_proxies and do not rely on the used HTTP scheme, host and port in your rules, you can also use the nginx.ingress.kubernetes.io/configuration-snippet and nginx.ingress.kubernetes.io/server-snippet annotations and use the configuration shown below.\nThis example is an exact copy of the configuration used in the very first integration option described above.\nnginx.ingress.kubernetes.io/configuration-snippet: | auth_request /_auth; auth_request_set $auth_cookie $upstream_http_set_cookie; add_header Set-Cookie $auth_cookie; auth_request_set $auth_header $upstream_http_authorization; proxy_set_header \u0026#39;Authorization\u0026#39; $auth_header; proxy_set_header Proxy \u0026#34;\u0026#34;; nginx.ingress.kubernetes.io/server-snippet: | location = /_auth { internal; access_log off; proxy_method $request_method; proxy_pass https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;$request_uri; proxy_pass_request_body off; proxy_set_header Content-Length \u0026#34;\u0026#34;; proxy_set_header Host $http_host; } # other annotations required Additional Resources Checkout the examples on GitHub for a working demo.\n","description":"This guide explains how to integrate heimdall with NGINX as well as with the NGINX Ingress Controller.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://nginx.org/\"\u003eNGINX\u003c/a\u003e is an HTTP and reverse proxy server which became famous as one of the fastest web servers out there, heimdall can be integrated with by making use of the \u003ca href=\"https://nginx.org/en/docs/http/ngx_http_auth_request_module.html\"\u003engx_http_auth_request_module\u003c/a\u003e. In such setup, NGINX delegates authentication and authorization to heimdall. If heimdall answers with a 2XX code, NGINX grants access and forwards the original request to the upstream service. If heimdall returns 401 or 403, the access is denied with the corresponding error code. Any other response code returned by heimdall is considered an error.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with NGINX requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e exposing its HTTP(s) endpoint.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_limitations\"\u003eLimitations\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNGINX \u003ca href=\"https://nginx.org/en/docs/http/ngx_http_auth_request_module.html\"\u003engx_http_auth_request_module\u003c/a\u003e responsible for communication with external authentication \u0026amp; authorization services, like heimdall, has a few limitations. As written above, it only supports 200, 401 and 403 response codes. That means:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eYou’ll not be able to drive redirects from heimdall, as 3xx error codes will result in 500 error returned by NGINX. You can partially overcome that limitation by letting heimdall respond with a 401 or 403 error code and mapping that to a redirect in NGINX itself, e.g. like shown below. This definitely not DRY and will not allow you using multiple identity provider if you need to\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"nginx\"\u003e\u003cspan class=\"c1\"\u003e# nginx.conf\u003c/span\u003e\n\u003cspan class=\"k\"\u003e...\u003c/span\u003e\n\n\u003cspan class=\"c1\"\u003e# if the ext auth server, like heimdall returns `401 not authorized`\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# then forward the request to the error401 block\u003c/span\u003e\n\u003cspan class=\"s\"\u003eerror_page\u003c/span\u003e \u003cspan class=\"mi\"\u003e401\u003c/span\u003e \u003cspan class=\"p\"\u003e=\u003c/span\u003e \u003cspan class=\"s\"\u003e@error401\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"k\"\u003elocation\u003c/span\u003e \u003cspan class=\"s\"\u003e@error401\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# redirect to the IdP for login\u003c/span\u003e\n \u003cspan class=\"kn\"\u003ereturn\u003c/span\u003e \u003cspan class=\"mi\"\u003e302\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://your-idp-service/login\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# you usually want your IdP to redirect back upon successful authentication\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# typically, you can achieve that by adding such query parameters like\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# return_to set to the value of the current request\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf there is no matching rule on heimdall side, heimdall responds with \u003ccode\u003e404 Not Found\u003c/code\u003e, which, as said above will be treated by NGINX as error. To avoid such situations, you can define a \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e, which is anyway recommended to have secure defaults\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_vanilla_nginx\"\u003eVanilla NGINX\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince NGINX is highly configurable and heimdall supports different integration options, you can use any of the configuration examples given below. All of these enable heimdall to build the URL of the protected backend server for rule matching purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn most cases you must configure heimdall to trust your NGINX instances by setting \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003e\u003ccode\u003etrusted_proxies\u003c/code\u003e\u003c/a\u003e. Exceptions are described in the sections below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_first_option\"\u003eForward only the path and query information\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith this method you don’t set any headers. That means, you cannot rely on the used HTTP scheme, or the host and port in your rules. Here NGINX uses the same HTTP method, used in the original request to it and add the path and query to the path/query URL used for communication with heimdall. That integration method does not require the configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e in heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"nginx\"\u003e\u003cspan class=\"c1\"\u003e# nginx.conf\u003c/span\u003e\n\u003cspan class=\"k\"\u003e...\u003c/span\u003e\n\n\u003cspan class=\"s\"\u003elocation\u003c/span\u003e \u003cspan class=\"n\"\u003e/\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eauth_request\u003c/span\u003e \u003cspan class=\"n\"\u003e/_auth\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eauth_request_set\u003c/span\u003e \u003cspan class=\"nv\"\u003e$auth_cookie\u003c/span\u003e \u003cspan class=\"nv\"\u003e$upstream_http_set_cookie\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eadd_header\u003c/span\u003e \u003cspan class=\"s\"\u003eSet-Cookie\u003c/span\u003e \u003cspan class=\"nv\"\u003e$auth_cookie\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eauth_request_set\u003c/span\u003e \u003cspan class=\"nv\"\u003e$authHeader0\u003c/span\u003e \u003cspan class=\"nv\"\u003e$upstream_http_authorization\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026#39;Authorization\u0026#39;\u003c/span\u003e \u003cspan class=\"nv\"\u003e$authHeader0\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# mitigate HTTPoxy Vulnerability\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eProxy\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003e...\u003c/span\u003e\n\u003cspan class=\"err\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"s\"\u003elocation\u003c/span\u003e \u003cspan class=\"p\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003e/_auth\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003einternal\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eaccess_log\u003c/span\u003e \u003cspan class=\"no\"\u003eoff\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_method\u003c/span\u003e \u003cspan class=\"nv\"\u003e$request_method\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_pass\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://heimdall:4455\u003c/span\u003e\u003cspan class=\"nv\"\u003e$request_uri\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_pass_request_body\u003c/span\u003e \u003cspan class=\"no\"\u003eoff\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eContent-Length\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eHost\u003c/span\u003e \u003cspan class=\"nv\"\u003e$http_host\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures NGINX to forward every request to the internal \u003ccode\u003e/_auth\u003c/code\u003e endpoint (this is where the actual heimdall integration happens - see below).\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWhen the response from heimdall returns, this and the next line set the Cookies set by heimdall in the response (whether you need this depends on your \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWhen the response from heimdall returns, this and the next line set the \u003ccode\u003eAuthorization\u003c/code\u003e header set by heimdall in the response (which header to set depends again on your \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is where the \u0026#34;magic\u0026#34; happens\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigure NGINX to use the HTTP method used by its client. Without this setting the implementation of \u003ccode\u003eproxy_path\u003c/code\u003e will use the HTTP GET method.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures NGINX to pass the request to heimdall and sets the request path and queries from the original request\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eDisables sending of the request body. If your heimdall rules make use of the body, you should set this to \u003ccode\u003eon\u003c/code\u003e and remove the next line.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLets the NGINX setting the \u003ccode\u003eHost\u003c/code\u003e header, so it is accessible to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_second_option\"\u003eForward all information in \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith this method you set the \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e and \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e to let heimdall know the host, respectively domain url and the used HTTP method.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCompared to the \u003ca href=\"#_first_option\"\u003eprevious integration\u003c/a\u003e option, the configuration only differs in the definition of the internal \u003ccode\u003e/_auth\u003c/code\u003e endpoint. So, the example configuration is limited to that part only.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nProper configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e is mandatory if using this option.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"nginx\"\u003e\u003cspan class=\"c1\"\u003e# nginx.conf\u003c/span\u003e\n\u003cspan class=\"k\"\u003e...\u003c/span\u003e\n\n\u003cspan class=\"s\"\u003elocation\u003c/span\u003e \u003cspan class=\"p\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003e/_auth\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"kn\"\u003einternal\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_pass\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://heimdall:4455\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_pass_request_body\u003c/span\u003e \u003cspan class=\"no\"\u003eoff\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eContent-Length\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Forwarded-Method\u003c/span\u003e \u003cspan class=\"nv\"\u003e$request_method\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Forwarded-Proto\u003c/span\u003e \u003cspan class=\"nv\"\u003e$scheme\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Forwarded-Host\u003c/span\u003e \u003cspan class=\"nv\"\u003e$http_host\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Forwarded-Uri\u003c/span\u003e \u003cspan class=\"nv\"\u003e$request_uri\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"kn\"\u003eproxy_set_header\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Forwarded-For\u003c/span\u003e \u003cspan class=\"nv\"\u003e$remote_addr\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures NGINX to pass the request to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet NGINX forward the used HTTP method to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet NGINX forward the used HTTP scheme to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet NGINX forward the used host to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet NGINX forward the used path and query parameter to heimdall.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_nginx_ingress_controller\"\u003eNGINX Ingress Controller\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h3\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_using_x_forwarded_headers\"\u003eUsing \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers\u003c/h4\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe configuration used in the example below requires proper configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e on heimdall side.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eGlobal configuration can be achieved by setting the following properties in controller \u003ccode\u003eConfigMap\u003c/code\u003e. If you install the NGINX controller via the helm chart, you can add these properties under the \u003ccode\u003econtroller.config\u003c/code\u003e property of your helm \u003ccode\u003evalues.yaml\u003c/code\u003e file.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eglobal-auth-url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://\u0026lt;heimdall\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eservice\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n\u003cspan class=\"na\"\u003eglobal-auth-response-headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n\u003cspan class=\"na\"\u003eglobal-auth-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Method $request_method;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Proto $scheme;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Host $http_host;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Uri $request_uri;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures the controller to use heimdall’s main service endpoint with \u003ccode\u003e\u0026lt;heimdall service name\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;namespace\u0026gt;\u003c/code\u003e and \u003ccode\u003e\u0026lt;port\u0026gt;\u003c/code\u003e depending on your configuration.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eLet NGINX forward the \u003ccode\u003eAuthorization\u003c/code\u003e header set by heimdall to the upstream service upon successful response. This configuration depends on\nyour \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003eContextualizers\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizers\u003c/a\u003e configuration. If not configured, NGINX will only react on \u003ccode\u003eSet-Cookie\u003c/code\u003e headers in responses from heimdall by default.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures the required headers to pass the information about the used HTTP scheme, host and port, request path and used query parameters to be forwarded to heimdall.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWithout that, heimdall will not be able extracting relevant information from the NGINX request as it does not support NGINX proprietary \u003ccode\u003eX-Original-Method\u003c/code\u003e and \u003ccode\u003eX-Original-Uri\u003c/code\u003e used by it for the same purposes.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith that in place, you can simply use the standard \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/ingress/\"\u003e\u003ccode\u003eIngress\u003c/code\u003e\u003c/a\u003e resource, and the NGINX Ingress Controller will ensure, each request will be analyzed by heimdall first.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis will result in an NGINX configuration corresponding to the integration option, described in the \u003ca href=\"#_second_option\"\u003eForward all information in \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers\u003c/a\u003e section.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_alternative_configuration\"\u003eAlternative Configuration\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAlternatively, if you don’t want configuring \u003ccode\u003etrusted_proxies\u003c/code\u003e and do not rely on the used HTTP scheme, host and port in your rules, you can also use the \u003ccode\u003elocation-snippet\u003c/code\u003e and the \u003ccode\u003eserver-snippet\u003c/code\u003e to the \u003ccode\u003eConfigMap\u003c/code\u003e of the NGINX Ingress Controller with values shown below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example is an exact copy of the configuration used in the very first \u003ca href=\"#_first_option\"\u003eintegration option\u003c/a\u003e described above.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elocation-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request /_auth;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request_set $auth_cookie $upstream_http_set_cookie;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eadd_header Set-Cookie $auth_cookie;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request_set $auth_header $upstream_http_authorization;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header \u0026#39;Authorization\u0026#39; $auth_header;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Proxy \u0026#34;\u0026#34;;\u003c/span\u003e\n\u003cspan class=\"na\"\u003eserver-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003elocation = /_auth {\u003c/span\u003e\n \u003cspan class=\"s\"\u003einternal;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eaccess_log off;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_method $request_method;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_pass https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;$request_uri;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_pass_request_body off;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Content-Length \u0026#34;\u0026#34;;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Host $http_host;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with the previous integration option, you can add these properties under the \u003ccode\u003econtroller.config\u003c/code\u003e property of your helm \u003ccode\u003evalues.yaml\u003c/code\u003e file if you install the NGINX Ingress Controller via helm.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_integration_on_ingress_resource_level\"\u003eIntegration on \u003ccode\u003eIngress\u003c/code\u003e Resource Level\u003c/h3\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_using_x_forwarded_headers_2\"\u003eUsing \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOne option to integrate heimdall with the NGINX Ingress Controller on the \u003ccode\u003eIngress\u003c/code\u003e resource level is making use of the \u003ccode\u003enginx.ingress.kubernetes.io/auth-url\u003c/code\u003e, \u003ccode\u003enginx.ingress.kubernetes.io/auth-response-headers\u003c/code\u003e and the \u003ccode\u003enginx.ingress.kubernetes.io/auth-snippet\u003c/code\u003e annotation as shown in the example below. This approach requires proper configuration of \u003ccode\u003etrusted_proxies\u003c/code\u003e on heimdall side. On NGINX Ingress Controller side you must allow the usage of \u003ccode\u003enginx.ingress.kubernetes.io/auth-snippet\u003c/code\u003e (See also \u003ca href=\"https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#allow-snippet-annotations\"\u003ehere\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003enginx.ingress.kubernetes.io/auth-url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://\u0026lt;heimdall\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eservice\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003enginx.ingress.kubernetes.io/auth-response-headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n\u003cspan class=\"na\"\u003enginx.ingress.kubernetes.io/auth-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Method $request_method;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Proto $scheme;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Host $http_host;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header X-Forwarded-Uri $request_uri;\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# other annotations required\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_alternative_configuration_2\"\u003eAlternative Configuration\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAlternatively, if you don’t want configuring \u003ccode\u003etrusted_proxies\u003c/code\u003e and do not rely on the used HTTP scheme, host and port in your rules, you can also use the \u003ccode\u003enginx.ingress.kubernetes.io/configuration-snippet\u003c/code\u003e and \u003ccode\u003enginx.ingress.kubernetes.io/server-snippet\u003c/code\u003e annotations and use the configuration shown below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example is an exact copy of the configuration used in the very first \u003ca href=\"#_first_option\"\u003eintegration option\u003c/a\u003e described above.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003enginx.ingress.kubernetes.io/configuration-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request /_auth;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request_set $auth_cookie $upstream_http_set_cookie;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eadd_header Set-Cookie $auth_cookie;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eauth_request_set $auth_header $upstream_http_authorization;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header \u0026#39;Authorization\u0026#39; $auth_header;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Proxy \u0026#34;\u0026#34;;\u003c/span\u003e\n\u003cspan class=\"na\"\u003enginx.ingress.kubernetes.io/server-snippet\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003elocation = /_auth {\u003c/span\u003e\n \u003cspan class=\"s\"\u003einternal;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eaccess_log off;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_method $request_method;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_pass https://\u0026lt;heimdall service name\u0026gt;.\u0026lt;namespace\u0026gt;.svc.cluster.local:\u0026lt;port\u0026gt;$request_uri;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_pass_request_body off;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Content-Length \u0026#34;\u0026#34;;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eproxy_set_header Host $http_host;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# other annotations required\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCheckout the examples on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e for a working demo.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"NGINX Integration","url":"/guides/proxies/nginx/"},{"categories":null,"content":" Traefik Proxy is a modern HTTP proxy and load balancer for microservices, heimdall can be integrated with via the ForwardAuth Middleware. If heimdall answers with a 2XX code, traefik grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\nPrerequisites Integration with traefik requires heimdall being operated in Decision Operation Mode.\nTraefik makes use of X-Forwarded-* HTTP headers to forward the HTTP method, protocol, host, etc. to the ForwardAuth middleware. By default, heimdall does not trust those. To allow heimdall making use of such headers, you must configure trusted proxies in heimdall’s main service configuration to contain the IPs or networks of your traefik instances. For test purposes, you can set it to \u0026#34;0.0.0.0/0\u0026#34;, which would basically disable the check and let heimdall trust requests from any source.\nTraefik can be configured statically, but also load dynamic configuration from many sources managed by so-called providers. The following sections describe how to integrate with heimdall using some of them.\nGlobal Configuration To let Traefik forward all incoming requests to heimdall, there is a need\nto configure the ForwardAuth middleware, and\nto add it to the list of middlewares that are prepended by default to the list of middlewares of each router associated to a named entry point.\nRegular Deployment If you are using Traefik outside of kubernetes, the above can be achieved by the following static configuration\nentryPoints: web: address: \u0026#34;:8080\u0026#34; middlewares: (1) - heimdall http: middlewares: heimdall: (2) forwardAuth: (3) address: \u0026#34;https://heimdall:4455\u0026#34; (4) authResponseHeaders: - Authorization (5) 1 The list of default middlewares. Here only the middleware named \u0026#34;heimdall\u0026#34; is included. That way, traefik will use this middleware for each and every request. 2 The definition of the middleware named \u0026#34;heimdall\u0026#34; 3 which is of type forwardAuth 4 Configures this middleware to forward requests to a service available under \u0026#34;heimdall\u0026#34; DNS name 5 Configures this middleware to forward the Authorization header from heimdall’s response to the upstream service Kubernetes Deployment If you are using Traefik as Ingress Controller or as Gateway API implementation in your kubernetes cluster, the required configuration is slightly different. The configuration of the entry point(s) stays the same, but the middleware needs to be deployed as a custom resource.\nHere an example for a Middleware custom resource:\napiVersion: traefik.io/v1alpha1 kind: Middleware metadata: (1) name: heimdall namespace: heimdall spec: forwardAuth: (2) address: \u0026#34;https://heimdall.heimdall.svc.cluster.local:4455\u0026#34; (3) authResponseHeaders: (4) - Authorization 1 The name and the namespace of the middleware. Both are set to heimdall here 2 The type of the middleware, which is of type forwardAuth 3 Configures this middleware to forward requests to the heimdall service. Here, the corresponding Service is named heimdall and is also located in the namespace named heimdall. 4 Configures this middleware to forward the Authorization header from heimdall’s response to the upstream service How to add this middleware to the default middleware list of a particular endpoint depends on the method used to install Traefik. If helm is used, you can configure that list by making use of the following values.yaml file:\nproviders: kubernetesCRD: enabled: true (1) ports: web: (2) middlewares: - heimdall-heimdall@kubernetescrd (3) websecure: (4) middlewares: - heimdall-heimdall@kubernetescrd 1 To let traefik load Middleware resources, like defined above, traefik’s kubernetesCRD provider must be enabled. Typically, it is enabled by default. 2 Traefik’s helm chart defines two entry points web for HTTP traffic and websecure for HTTPS traffic. Here we configure the web endpoint to use our middleware 3 Reference to the Middleware resource, defined above. The general structure is \u0026lt;middleware name\u0026gt;-\u0026lt;middleware namespace\u0026gt;@\u0026lt;provider\u0026gt;. Since our middleware resource is loaded by the kubernetescrd provider, resides in the heimdall namespace, and is named heimdall, the reference heimdall-heimdall@kubernetescrd is used. 4 Here we configure the websecure endpoint, which, as written above, is configured via helm chart for HTTPS traffic. The actual configuration is identical to the configuration for the web endpoint. Route-based Configuration with Docker The integration option, described here makes use of the Docker Provider for configuration discovery.\nThe following docker-compose.yaml file shows a minimal required configuration.\nservices: proxy: image: traefik:2.11.0 ports: - \u0026#34;9090:9090\u0026#34; command: \u0026gt; --providers.docker=true (1) --providers.docker.exposedbydefault=false --entryPoints.http.address=\u0026#34;:9090\u0026#34; volumes: - \u0026#34;/var/run/docker.sock:/var/run/docker.sock:ro\u0026#34; (2) # other config options labels: # other labels - traefik.http.middlewares.heimdall.forwardauth.address=https://heimdall:4455 (3) - traefik.http.middlewares.heimdall.forwardauth.authResponseHeaders=Authorization (4) heimdall: image: dadrus/heimdall:dev # further config upstream: # image and config of your upstream service labels: # other labels - traefik.http.routers.upstream.middlewares=heimdall (5) 1 This and the next line configures the docker provider 2 The docker provider reads the configuration from labels of the services and requires access to the docker socket for this purpose 3 Configuration of the ForwardAuth middleware to forward incoming requests to heimdall. The name of middleware is set to \u0026#34;heimdall\u0026#34; here. 4 Configuration of the ForwardAuth middleware to forward the Authorization header from heimdall’s response to the upstream service 5 Configuration of the required middlewares on the route level of a particular service. Here only the middleware named \u0026#34;heimdall\u0026#34; is referenced. Without that label, traefik will not forward requests to heimdall before routing them to that upstream service. Traefik as Ingress Controller If you have Traefik as Ingress Controller in your Kubernetes cluster, you can simply integrate heimdall globally as descibed in Global Configuration chapter above and make use of the standard Ingress resource.\nIf you are using traefik’s proprietary IngressRoute custom resource instead of kubernetes standard Ingress one, you can also reference the Middleware resource locally. This option is shown in the snippet below.\napiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: (1) name: demo-app namespace: demo spec: entryPoints: - web (2) routes: - kind: Rule match: Host(`demo-app.local`) \u0026amp;\u0026amp; PathPrefix(`/`) middlewares: (3) - name: heimdall namespace: heimdall services: (4) - kind: Service name: demo-app namespace: demo port: app-port 1 metadata, like name and the namespace of the IngressRoute resource 2 The traefik entry points to attach this resource to. Here only web entry point is referenced 3 List of the middlewares to be applied. Here the Middleware named heimdall in the namespace heimdall is referenced. By default, IngressRoute resources are not allowed to reference resources in namespaces different from the own namespace. If your Middleware resource, like also shown here, is deployed in another namespace, you have to allow that. If traefik is installed via helm, it can be achieved by setting providers.kubernetesCRD.allowCrossNamespace to true (See also here). 4 The reference to the Service, the requests should be forwarded to. Traefik as Gateway API implementation If you have Traefik as Gateway API implementation in your Kubernetes cluster, you can simply integrate heimdall globally as descibed in Global Configuration chapter above and make use of the standard HTTPRoute resource.\nAdditional Resources A fully working example with Traefik is shown in the Protect an Application quickstart and is also available on GitHub.\n","description":"This guide explains how to integrate heimdall with Traefik Proxy.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://doc.traefik.io/traefik/\"\u003eTraefik Proxy\u003c/a\u003e is a modern HTTP proxy and load balancer for microservices, heimdall can be integrated with via the \u003ca href=\"https://doc.traefik.io/traefik/middlewares/http/forwardauth/\"\u003eForwardAuth Middleware\u003c/a\u003e. If heimdall answers with a 2XX code, traefik grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is returned to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIntegration with traefik requires heimdall being operated in \u003ca href=\"/docs/concepts/operating_modes/#_decision_mode\"\u003eDecision Operation Mode\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTraefik makes use of \u003ccode\u003eX-Forwarded-*\u003c/code\u003e HTTP headers to forward the HTTP method, protocol, host, etc. to the ForwardAuth middleware. By default, heimdall does not trust those. To allow heimdall making use of such headers, you must configure \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003etrusted proxies\u003c/a\u003e in heimdall’s main service configuration to contain the IPs or networks of your traefik instances. For test purposes, you can set it to \u0026#34;0.0.0.0/0\u0026#34;, which would basically disable the check and let heimdall trust requests from any source.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTraefik can be configured statically, but also load dynamic configuration from many sources managed by so-called providers. The following sections describe how to integrate with heimdall using some of them.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_global_configuration\"\u003eGlobal Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo let Traefik forward all incoming requests to heimdall, there is a need\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eto configure the \u003ca href=\"https://doc.traefik.io/traefik/middlewares/http/forwardauth/\"\u003eForwardAuth\u003c/a\u003e middleware, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eto add it to the list of \u003ca href=\"https://doc.traefik.io/traefik/routing/entrypoints/#middlewares\"\u003emiddlewares\u003c/a\u003e that are prepended by default to the list of middlewares of each router associated to a named entry point.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_regular_deployment\"\u003eRegular Deployment\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you are using Traefik outside of kubernetes, the above can be achieved by the following static configuration\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eentryPoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eweb\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e:8080\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003emiddlewares\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003ehttp\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emiddlewares\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eforwardAuth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://heimdall:4455\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eauthResponseHeaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe list of default middlewares. Here only the middleware named \u0026#34;heimdall\u0026#34; is included. That way, traefik will use this middleware for each and every request.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe definition of the middleware named \u0026#34;heimdall\u0026#34;\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003ewhich is of type \u003ca href=\"https://doc.traefik.io/traefik/middlewares/http/forwardauth/\"\u003e\u003ccode\u003eforwardAuth\u003c/code\u003e\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures this middleware to forward requests to a service available under \u0026#34;heimdall\u0026#34; DNS name\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures this middleware to forward the \u003ccode\u003eAuthorization\u003c/code\u003e header from heimdall’s response to the upstream service\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_kubernetes_deployment\"\u003eKubernetes Deployment\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you are using Traefik as \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/\"\u003eIngress Controller\u003c/a\u003e or as \u003ca href=\"https://gateway-api.sigs.k8s.io/\"\u003eGateway API\u003c/a\u003e implementation in your kubernetes cluster, the required configuration is slightly different. The configuration of the entry point(s) stays the same, but the middleware needs to be deployed as a custom resource.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere an example for a \u003ca href=\"https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/#kind-middleware\"\u003e\u003ccode\u003eMiddleware\u003c/code\u003e\u003c/a\u003e custom resource:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.io/v1alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eMiddleware\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforwardAuth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://heimdall.heimdall.svc.cluster.local:4455\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eauthResponseHeaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe name and the namespace of the middleware. Both are set to \u003ccode\u003eheimdall\u003c/code\u003e here\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe type of the middleware, which is of type \u003ca href=\"https://doc.traefik.io/traefik/middlewares/http/forwardauth/\"\u003e\u003ccode\u003eforwardAuth\u003c/code\u003e\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures this middleware to forward requests to the heimdall service. Here, the corresponding \u003ccode\u003eService\u003c/code\u003e is named \u003ccode\u003eheimdall\u003c/code\u003e and is also located in the namespace named \u003ccode\u003eheimdall\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfigures this middleware to forward the \u003ccode\u003eAuthorization\u003c/code\u003e header from heimdall’s response to the upstream service\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow to add this middleware to the default middleware list of a particular endpoint depends on the method used to install Traefik. If helm is used, you can configure that list by making use of the following \u003ccode\u003evalues.yaml\u003c/code\u003e file:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eproviders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekubernetesCRD\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n\n\u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eweb\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003emiddlewares\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-heimdall@kubernetescrd\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ewebsecure\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003emiddlewares\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall-heimdall@kubernetescrd\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eTo let traefik load \u003ccode\u003eMiddleware\u003c/code\u003e resources, like defined above, traefik’s \u003ccode\u003ekubernetesCRD\u003c/code\u003e provider must be enabled. Typically, it is enabled by default.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eTraefik’s helm chart defines two entry points \u003ccode\u003eweb\u003c/code\u003e for HTTP traffic and \u003ccode\u003ewebsecure\u003c/code\u003e for HTTPS traffic. Here we configure the \u003ccode\u003eweb\u003c/code\u003e endpoint to use our middleware\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eReference to the \u003ccode\u003eMiddleware\u003c/code\u003e resource, defined above. The general structure is \u003ccode\u003e\u0026lt;middleware name\u0026gt;-\u0026lt;middleware namespace\u0026gt;@\u0026lt;provider\u0026gt;\u003c/code\u003e. Since our middleware resource is loaded by the \u003ccode\u003ekubernetescrd\u003c/code\u003e provider, resides in the \u003ccode\u003eheimdall\u003c/code\u003e namespace, and is named \u003ccode\u003eheimdall\u003c/code\u003e, the reference \u003ccode\u003eheimdall-heimdall@kubernetescrd\u003c/code\u003e is used.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we configure the \u003ccode\u003ewebsecure\u003c/code\u003e endpoint, which, as written above, is configured via helm chart for HTTPS traffic. The actual configuration is identical to the configuration for the \u003ccode\u003eweb\u003c/code\u003e endpoint.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_route_based_configuration_with_docker\"\u003eRoute-based Configuration with Docker\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe integration option, described here makes use of the \u003ca href=\"https://doc.traefik.io/traefik/providers/docker/\"\u003eDocker Provider\u003c/a\u003e for configuration discovery.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following \u003ccode\u003edocker-compose.yaml\u003c/code\u003e file shows a minimal required configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eproxy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik:2.11.0\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e9090:9090\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--providers.docker=true \u003c/span\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"s\"\u003e--providers.docker.exposedbydefault=false\u003c/span\u003e\n \u003cspan class=\"s\"\u003e--entryPoints.http.address=\u0026#34;:9090\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e/var/run/docker.sock:/var/run/docker.sock:ro\u0026#34;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"c1\"\u003e# other config options\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other labels\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.middlewares.heimdall.forwardauth.address=https://heimdall:4455\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.middlewares.heimdall.forwardauth.authResponseHeaders=Authorization\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edadrus/heimdall:dev\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# further config\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eupstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# image and config of your upstream service\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other labels\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.http.routers.upstream.middlewares=heimdall\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis and the next line configures the docker provider\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe docker provider reads the configuration from labels of the services and requires access to the docker socket for this purpose\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfiguration of the \u003ca href=\"https://doc.traefik.io/traefik/middlewares/http/forwardauth/\"\u003eForwardAuth\u003c/a\u003e middleware to forward incoming requests to heimdall. The name of middleware is set to \u0026#34;heimdall\u0026#34; here.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfiguration of the ForwardAuth middleware to forward the \u003ccode\u003eAuthorization\u003c/code\u003e header from heimdall’s response to the upstream service\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eConfiguration of the required middlewares on the route level of a particular service. Here only the middleware named \u0026#34;heimdall\u0026#34; is referenced. Without that label, traefik will not forward requests to heimdall before routing them to that upstream service.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_traefik_as_ingress_controller\"\u003eTraefik as Ingress Controller\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you have Traefik as Ingress Controller in your Kubernetes cluster, you can simply integrate heimdall globally as descibed in \u003ca href=\"#_global_configuration\"\u003eGlobal Configuration\u003c/a\u003e chapter above and make use of the standard \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/ingress/\"\u003eIngress resource\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you are using traefik’s proprietary \u003ca href=\"https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/#kind-ingressroute\"\u003e\u003ccode\u003eIngressRoute\u003c/code\u003e\u003c/a\u003e custom resource instead of kubernetes standard \u003ca href=\"https://kubernetes.io/docs/concepts/services-networking/ingress/\"\u003e\u003ccode\u003eIngress\u003c/code\u003e\u003c/a\u003e one, you can also reference the \u003ca href=\"https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/#kind-middleware\"\u003e\u003ccode\u003eMiddleware\u003c/code\u003e\u003c/a\u003e resource locally. This option is shown in the snippet below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etraefik.io/v1alpha1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eIngressRoute\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo-app\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eentryPoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eweb\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRule\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eHost(`demo-app.local`) \u0026amp;\u0026amp; PathPrefix(`/`)\u003c/span\u003e\n \u003cspan class=\"na\"\u003emiddlewares\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eService\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo-app\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edemo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapp-port\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003emetadata\u003c/code\u003e, like name and the namespace of the \u003ccode\u003eIngressRoute\u003c/code\u003e resource\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe traefik entry points to attach this resource to. Here only \u003ccode\u003eweb\u003c/code\u003e entry point is referenced\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eList of the middlewares to be applied. Here the \u003ccode\u003eMiddleware\u003c/code\u003e named \u003ccode\u003eheimdall\u003c/code\u003e in the namespace \u003ccode\u003eheimdall\u003c/code\u003e is referenced.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nBy default, \u003ccode\u003eIngressRoute\u003c/code\u003e resources are not allowed to reference resources in namespaces different from the own namespace. If your \u003ccode\u003eMiddleware\u003c/code\u003e resource, like also shown here, is deployed in another namespace, you have to allow that. If traefik is installed via helm, it can be achieved by setting \u003ccode\u003eproviders.kubernetesCRD.allowCrossNamespace\u003c/code\u003e to \u003ccode\u003etrue\u003c/code\u003e (See also \u003ca href=\"https://doc.traefik.io/traefik/providers/kubernetes-crd/#allowcrossnamespace\"\u003ehere\u003c/a\u003e).\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe reference to the \u003ccode\u003eService\u003c/code\u003e, the requests should be forwarded to.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_traefik_as_gateway_api_implementation\"\u003eTraefik as Gateway API implementation\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you have Traefik as \u003ca href=\"https://gateway-api.sigs.k8s.io/\"\u003eGateway API\u003c/a\u003e implementation in your Kubernetes cluster, you can simply integrate heimdall globally as descibed in \u003ca href=\"#_kubernetes_deployment\"\u003eGlobal Configuration\u003c/a\u003e chapter above and make use of the standard \u003ca href=\"https://gateway-api.sigs.k8s.io/api-types/httproute\"\u003e\u003ccode\u003eHTTPRoute\u003c/code\u003e\u003c/a\u003e resource.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_additional_resources\"\u003eAdditional Resources\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA fully working example with Traefik is shown in the \u003ca href=\"/docs/getting_started/protect_an_app/\"\u003eProtect an Application\u003c/a\u003e quickstart and is also available on \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/examples\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","API Gateways \u0026 Proxies"],"tags":null,"title":"Traefik Proxy Integration","url":"/guides/proxies/traefik/"},{"categories":null,"content":" The Protect an Application quickstart guide, describing the steps required to protect an application with heimdall, shows already how OPA can be used with heimdall. This document provides some further examples.\nExample 1: Sharing Service Imagine you have a sharing service, e.g. to let friends share all their photos with each other and the API looks roughly as follows:\nGET /\u0026lt;user\u0026gt;/photos returns all the photos of the user either to the owner of the photo collection itself or to its friends.\nTo achieve this using OPA, we would need something like the following Rego policy:\npackage share_photos default allow = false # user is owner. that is, the value of first path # fragment is equal to the identified user allow { split(input.path, \u0026#34;/\u0026#34;)[1] == input.user } # user is friend. that is, the user referenced by the # first path fragment has the identified user in its friends list allow { data.friends[split(input.path, \u0026#34;/\u0026#34;)[1]][_] == input.user } It expects two pieces of information in the payload to the OPA instance:\nthe actual user, making the request and\nthe path to witch the request is made\nSo something like this: { \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;alice\u0026#34;, \u0026#34;path\u0026#34;: \u0026#34;bob/photos\u0026#34; } }. Since the Rego policy defined above returns just true or false, the corresponding response from the OPA endpoint would be { \u0026#34;result\u0026#34;: true } or { \u0026#34;result\u0026#34;: false }. Given this and assuming the above policy can be used by making requests to https://opa.local/v1/data/share_photos/policy/allow, the configuration of the Remote Authorizer would look like follows:\nid: photos_access type: remote config: endpoint: url: https://opa.local/v1/data/share_photos/policy/allow payload: | { \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }}, \u0026#34;path\u0026#34;: {{ quote .RequestURL.Path }} } } expressions: - expression: | Payload.result == true Here the entire authorization happens within heimdall and is completely outsourced from the business logic of our sharing service.\nExample 2: Membership Verification Imagine you have a billing service, which requires information about the membership of a user to different groups, which represent different subscription options for you entire offering. Depending on this information your service would create invoices with different amounts. The imaginary API of that service could look like follows:\nPOST /create_invoice to invoice the identified user.\nYou could perform the required query to OPA entirely in your service and use the retrieved group memberships then. Alternatively, you could outsource the communication to OPA to heimdall and deal only with the group membership information in your service. Compared to the Sharing Service example, this time heimdall would not perform any authorization, but rather enrich the subject information with further information. This way, we’re not going to use a Authorizer, but a Generic Contextualizer instead. As with Sharing Service example, there is a need for a Rego policy, which could look like this:\npackage invoice groups_graph[data.groups[subject].name] = edges { edges := data.groups[subject].member_of } member_of_groups[subject] = groups { groups_graph[subject] groups := graph.reachable(groups_graph, {subject}) } groups { member_of_groups[input.user][_] } It expects just one piece of information, namely the actual user, making the request. So something like this: { \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;alice\u0026#34; } }. Since the Rego policy defined above returns a list of groups, the corresponding response from the OPA endpoint would be { \u0026#34;result\u0026#34;: [\u0026#34;group1\u0026#34;, \u0026#34;group2\u0026#34;] }. Given this and assuming the above policy can be used by making requests to https://opa.local/v1/data/invoice/policy/groups and the authentication to that endpoint requires basic authentication, the configuration of the Generic Contextualizer would look like follows:\nid: billing_contextualizer type: generic config: endpoint: url: https://opa.local/v1/data/invoice/policy/groups auth: type: basic_auth config: user: MyOpaUser password: SuperSecretPassword payload: | { \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }} } } Upon successful execution of the corresponding request, the response from the OPA endpoint will be stored in the Outputs[\u0026#34;billing_contextualizer\u0026#34;] field. That way, you can use that information in a Finalizer to forward the group membership to the billing service API.\n","description":"This guide provides examples on how to integrate heimdall with the Open Policy Agent.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"/docs/getting_started/protect_an_app/\"\u003eProtect an Application\u003c/a\u003e quickstart guide, describing the steps required to protect an application with heimdall, shows already how \u003ca href=\"https://www.openpolicyagent.org/\"\u003eOPA\u003c/a\u003e can be used with heimdall. This document provides some further examples.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_example_1_sharing_service\"\u003eExample 1: Sharing Service\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you have a sharing service, e.g. to let friends share all their photos with each other and the API looks roughly as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eGET /\u0026lt;user\u0026gt;/photos\u003c/code\u003e returns all the photos of the user either to the owner of the photo collection itself or to its friends.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo achieve this using OPA, we would need something like the following \u003ca href=\"https://www.openpolicyagent.org/docs/latest/policy-language/\"\u003eRego\u003c/a\u003e policy:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"rego\"\u003e\u003cspan class=\"ow\"\u003epackage\u003c/span\u003e \u003cspan class=\"n\"\u003eshare_photos\u003c/span\u003e\n\n\u003cspan class=\"ow\"\u003edefault\u003c/span\u003e \u003cspan class=\"n\"\u003eallow\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n\n\u003cspan class=\"c1\"\u003e# user is owner. that is, the value of first path\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# fragment is equal to the identified user\u003c/span\u003e\n\u003cspan class=\"n\"\u003eallow\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"n\"\u003esplit\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003epath\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)[\u003c/span\u003e\u003cspan class=\"m\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003euser\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"c1\"\u003e# user is friend. that is, the user referenced by the\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# first path fragment has the identified user in its friends list\u003c/span\u003e\n\u003cspan class=\"n\"\u003eallow\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"n\"\u003edata\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003efriends\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003esplit\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003epath\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)[\u003c/span\u003e\u003cspan class=\"m\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e]][\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003euser\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIt expects two pieces of information in the payload to the OPA instance:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ethe actual user, making the request and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe path to witch the request is made\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSo something like this: \u003ccode\u003e{ \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;alice\u0026#34;, \u0026#34;path\u0026#34;: \u0026#34;bob/photos\u0026#34; } }\u003c/code\u003e. Since the Rego policy defined above returns just \u003ccode\u003etrue\u003c/code\u003e or \u003ccode\u003efalse\u003c/code\u003e, the corresponding response from the OPA endpoint would be \u003ccode\u003e{ \u0026#34;result\u0026#34;: true }\u003c/code\u003e or \u003ccode\u003e{ \u0026#34;result\u0026#34;: false }\u003c/code\u003e. Given this and assuming the above policy can be used by making requests to \u003ccode\u003ehttps://opa.local/v1/data/share_photos/policy/allow\u003c/code\u003e, the configuration of the \u003ca href=\"/docs/mechanisms/authorizers/#_remote\"\u003eRemote Authorizer\u003c/a\u003e would look like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ephotos_access\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://opa.local/v1/data/share_photos/policy/allow\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{ \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }}, \u0026#34;path\u0026#34;: {{ quote .RequestURL.Path }} } }\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.result == true\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere the entire authorization happens within heimdall and is completely outsourced from the business logic of our sharing service.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_example_2_membership_verification\"\u003eExample 2: Membership Verification\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you have a billing service, which requires information about the membership of a user to different groups, which represent different subscription options for you entire offering. Depending on this information your service would create invoices with different amounts. The imaginary API of that service could look like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ePOST /create_invoice\u003c/code\u003e to invoice the identified user.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou could perform the required query to OPA entirely in your service and use the retrieved group memberships then. Alternatively, you could outsource the communication to OPA to heimdall and deal only with the group membership information in your service. Compared to the \u003ca href=\"#_example_1_sharing_service\"\u003eSharing Service\u003c/a\u003e example, this time heimdall would not perform any authorization, but rather enrich the subject information with further information. This way, we’re not going to use a \u003ca href=\"/docs/mechanisms/authorizers/\"\u003eAuthorizer\u003c/a\u003e, but a \u003ca href=\"/docs/mechanisms/contextualizers/#_generic\"\u003eGeneric Contextualizer\u003c/a\u003e instead. As with \u003ca href=\"#_example_1_sharing_service\"\u003eSharing Service\u003c/a\u003e example, there is a need for a \u003ca href=\"https://www.openpolicyagent.org/docs/latest/policy-language/\"\u003eRego\u003c/a\u003e policy, which could look like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"rego\"\u003e\u003cspan class=\"ow\"\u003epackage\u003c/span\u003e \u003cspan class=\"n\"\u003einvoice\u003c/span\u003e\n\n\u003cspan class=\"n\"\u003egroups_graph\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003edata\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003egroups\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003esubject\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"n\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eedges\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"n\"\u003eedges\u003c/span\u003e \u003cspan class=\"o\"\u003e:=\u003c/span\u003e \u003cspan class=\"n\"\u003edata\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003egroups\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003esubject\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"n\"\u003emember_of\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"n\"\u003emember_of_groups\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003esubject\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003egroups\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"n\"\u003egroups_graph\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003esubject\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n \u003cspan class=\"n\"\u003egroups\u003c/span\u003e \u003cspan class=\"o\"\u003e:=\u003c/span\u003e \u003cspan class=\"n\"\u003egraph\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ereachable\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003egroups_graph\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"n\"\u003esubject\u003c/span\u003e\u003cspan class=\"p\"\u003e})\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"n\"\u003egroups\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"n\"\u003emember_of_groups\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003euser\u003c/span\u003e\u003cspan class=\"p\"\u003e][\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIt expects just one piece of information, namely the actual user, making the request. So something like this: \u003ccode\u003e{ \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;alice\u0026#34; } }\u003c/code\u003e. Since the Rego policy defined above returns a list of groups, the corresponding response from the OPA endpoint would be \u003ccode\u003e{ \u0026#34;result\u0026#34;: [\u0026#34;group1\u0026#34;, \u0026#34;group2\u0026#34;] }\u003c/code\u003e. Given this and assuming the above policy can be used by making requests to \u003ccode\u003ehttps://opa.local/v1/data/invoice/policy/groups\u003c/code\u003e and the authentication to that endpoint requires basic authentication, the configuration of the \u003ca href=\"/docs/mechanisms/contextualizers/#_generic\"\u003eGeneric Contextualizer\u003c/a\u003e would look like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebilling_contextualizer\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://opa.local/v1/data/invoice/policy/groups\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eMyOpaUser\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSuperSecretPassword\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{ \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }} } }\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUpon successful execution of the corresponding request, the response from the OPA endpoint will be stored in the \u003ccode\u003eOutputs[\u0026#34;billing_contextualizer\u0026#34;]\u003c/code\u003e field. That way, you can use that information in a \u003ca href=\"/docs/mechanisms/finalizers/\"\u003eFinalizer\u003c/a\u003e to forward the group membership to the billing service API.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","Authorization Services"],"tags":null,"title":"Integration with OPA","url":"/guides/authz/opa/"},{"categories":null,"content":" OpenFGA is inspired by Google’s Zanzibar, Google’s Relationship Based Access Control system and allows easily implementing authorization for any kind of application relying on Role-Based Access Control with additional Attribute-Based Access Control capabilities.\nThis guide is based on the OpenFGA’s official Getting Started guide and highlights the relevant differences. It mimics a RESTful document management API, allowing listing, creating, reading, updating, and deleting documents. The API consists of two endpoints:\n/document/\u0026lt;id\u0026gt; with id being the id of the document and the HTTP verbs reflecting the actual operations. E.g. a GET /document/1234 request should read the document with the id 1234.\n/documents which supports the HTTP GET verb only and allows the user to list the documents it can access.\nThe identity of the user will be taken from a JWT.\nEven this guide addresses OpenFGA, it actually covers integration with any ReBAC system, be it Ory’s Keto, SpiceDB from AuthZed, or any other system inspired by Google’s Zanzibar. Prerequisites To be able to follow this guide, you’ll need the following tools installed locally:\nDocker,\ndocker-compose, and\na text editor of your choice.\nConfigure the Base Setup Create a directory in which we’re going to create further directories and files required for the setup and switch to it.\nCreate a directory named rules. We’ll add the heimdall rule to it after our setup is started.\nCreate a docker-compose.yaml file with the following contents\nservices: heimdall: (1) image: dadrus/heimdall:dev container_name: heimdall ports: - \u0026#34;9090:4455\u0026#34; volumes: - ./heimdall-config.yaml:/etc/heimdall/config.yaml:ro - ./rules:/etc/heimdall/rules:ro - ./signer.pem:/etc/heimdall/signer.pem:ro command: serve proxy -c /etc/heimdall/config.yaml --insecure upstream: (2) image: containous/whoami:latest container_name: upstream command: - --port=8081 openfga: (3) image: openfga/openfga:latest container_name: openfga command: run ports: - \u0026#34;8080:8080\u0026#34; idp: (4) image: nginx:1.25.4 volumes: - ./idp.nginx:/etc/nginx/nginx.conf:ro - ./jwks.json:/var/www/nginx/jwks.json:ro 1 These lines configure heimdall to use a config file, we’re going to configure next and a rule directory, we’ll add our rules to. We’re using the --insecure flag here to simplify our setup, which disables enforcement of some security settings you can learn about more here. 2 Here, we define the \u0026#34;upstream\u0026#34; service, which just echoes back everything it receives. 3 And these lines configure our OpenFGA instance. It is the simplest setup, described in Setup OpenFGA with Docker 4 This is an NGINX service, which mimics an IDP system and exposes an JWKS endpoint with key material, heimdall is going to use to validate the JWT you’re going to use. Create a configuration file for heimdall, named heimdall-config.yaml with the following contents.\nmechanisms: authenticators: - id: jwt_auth (1) type: jwt config: jwks_endpoint: http://idp:8080/.well-known/jwks assertions: issuers: - demo_issuer authorizers: - id: openfga_check (2) type: remote config: endpoint: http://openfga:8080/stores/{{ .Values.store_id }}/check (3) payload: | (4) { \u0026#34;authorization_model_id\u0026#34;: \u0026#34;{{ .Values.model_id }}\u0026#34;, \u0026#34;tuple_key\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;, \u0026#34;relation\u0026#34;:\u0026#34;{{ .Values.relation }}\u0026#34;, \u0026#34;object\u0026#34;:\u0026#34;{{ .Values.object }}\u0026#34; } } expressions: - expression: | Payload.allowed == true (5) contextualizers: - id: openfga_list (6) type: generic config: endpoint: http://openfga:8080/stores/{{ .Values.store_id }}/list-objects (7) payload: | (8) { \u0026#34;authorization_model_id\u0026#34;: \u0026#34;{{ .Values.model_id }}\u0026#34;, \u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;, \u0026#34;relation\u0026#34;:\u0026#34;{{ .Values.relation }}\u0026#34;, \u0026#34;type\u0026#34;:\u0026#34;document\u0026#34; } finalizers: - id: create_jwt (9) type: jwt config: signer: key_store: path: /etc/heimdall/signer.pem providers: file_system: (10) src: /etc/heimdall/rules watch: true 1 This and the following lines define and configure the jwt authenticator named jwt_auth. With the given configuration it will check whether a request contains an Authorization header with a bearer token in JWT format and validate it using key material fetched from the JWKS endpoint. 2 Here we define and configure a remote authorizer named openfga_check, which we’re going to use for the actual authorization purposes in our rules. 3 Here we define the endpoint to be used for the authorization checks. Most probably, you’ll want to hard code your OpenFGA model id. Since, we’re going to create the model, when we start our setup, we’ll reference it in our rule via store_id. We use a very simple endpoint configuration here by just specifying the actual url. If required, you can specify API keys, and many more. Take a look at the linked documentation of this property. 4 This is the definition of our payload to be sent to the check endpoint. As we don’t know the model id as well, we’ll configure it in our rule. The user will be taken from the Subject create by heimdall, and the relation and object will be specified in our rule. 5 In case of a successful response, the response from the check endpoint will look like {\u0026#34;allowed\u0026#34;: true}. Otherwise, it will be {\u0026#34;allowed\u0026#34;: false}. With the expression here, we perform the required verification. 6 Here we define and configure a generic contextualizer named openfga_list. 7 As with the authorization mechanism, defined above, here we configure the endpoint to list the allowed objects. 8 The payload configuration used while communicating to the configured endpoint. 9 The following two lines define the jwt finalizer. With the given configuration, it will create a jwt out of the subject object with standard claims and set the sub claim to the value of subject’s ID. 10 The last few lines of the configure the file_system provider, which allows loading of regular rules from the file system. Create a file, named signer.pem with the following content. This is our key store with a private key, you’ve seen in the configuration above.\n-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy 1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI zlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X XVwR/5tokqFVrFxt/5c1x7VdccF4nNM= -----END EC PRIVATE KEY----- Do not use it for purposes beyond this tutorial! Configure NGINX to expose a static endpoint serving a JWKS document under the .well-known path, so heimdall is able to verify the JWT, we’re going to use. Create a file named idp.nginx with the following content:\nworker_processes 1; user nginx; pid /var/run/nginx.pid; events { worker_connections 1024; } http { keepalive_timeout 65; server { listen 8080; location /.well-known/jwks { default_type application/json; root /var/www/nginx; try_files /jwks.json =404; } } } In addition, create a file named jwks.json with the public key required to verify the tokens we’re going to use.\n{ \u0026#34;keys\u0026#34;: [ { \u0026#34;use\u0026#34;: \u0026#34;sig\u0026#34;, \u0026#34;kty\u0026#34;: \u0026#34;EC\u0026#34;, \u0026#34;kid\u0026#34;: \u0026#34;key-2\u0026#34;, \u0026#34;crv\u0026#34;: \u0026#34;P-256\u0026#34;, \u0026#34;alg\u0026#34;: \u0026#34;ES256\u0026#34;, \u0026#34;x\u0026#34;: \u0026#34;NnU0iWRq7szZP_8Ir3D4BShUEtcW1dHpuvlCgB6ecE0\u0026#34;, \u0026#34;y\u0026#34;: \u0026#34;X71tZm51ovUPFNKE0bsi5XF-FtIykEfk1O83EHNkSdo\u0026#34; } ] } Create Authorization Model \u0026amp; Rules The static configuration of our services is in place. Let us now create the actual authorization model and based on it the required heimdall rules.\nStart our setup with docker compose up and wait until all services are up and running.\nCreate the OpenFGA store as also described in Create Store with\ncurl -X POST http://127.0.0.1:8080/stores \\ -H \u0026#34;content-type: application/json\u0026#34; \\ -d \u0026#39;{\u0026#34;name\u0026#34;: \u0026#34;FGA Demo Store\u0026#34;}\u0026#39; This call should result in an output similar to\n{ \u0026#34;id\u0026#34;:\u0026#34;01HSXG2XSZJMQG99EVXB4QQX8P\u0026#34;, \u0026#34;name\u0026#34;:\u0026#34;FGA Demo Store\u0026#34;, \u0026#34;created_at\u0026#34;:\u0026#34;2024-03-26T13:44:37.439559338Z\u0026#34;, \u0026#34;updated_at\u0026#34;:\u0026#34;2024-03-26T13:44:37.439559338Z\u0026#34; } Note or write down the value of the store id returned.\nConfigure the authorization model as also described in Configure Model with\ncurl -X POST http://127.0.0.1:8080/stores/\u0026lt;the id from above\u0026gt;/authorization-models \\ -H \u0026#34;content-type: application/json\u0026#34; \\ -d \u0026#39;{\u0026#34;schema_version\u0026#34;:\u0026#34;1.1\u0026#34;,\u0026#34;type_definitions\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;},{\u0026#34;type\u0026#34;:\u0026#34;document\u0026#34;,\u0026#34;relations\u0026#34;:{\u0026#34;reader\u0026#34;:{\u0026#34;this\u0026#34;:{}},\u0026#34;writer\u0026#34;:{\u0026#34;this\u0026#34;:{}},\u0026#34;owner\u0026#34;:{\u0026#34;this\u0026#34;:{}}},\u0026#34;metadata\u0026#34;:{\u0026#34;relations\u0026#34;:{\u0026#34;reader\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]},\u0026#34;writer\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]},\u0026#34;owner\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]}}}}]}\u0026#39; This call should result in an output similar to\n{ \u0026#34;authorization_model_id\u0026#34;:\u0026#34;01HSXG7TBQEJ7GBPKQR2VYH24G\u0026#34; } Note or write down the value of authorization_model_id.\nLet us now create a rule set for heimdall. Create a file named demo.yaml with the following contents in the rules directory\nversion: \u0026#34;1alpha4\u0026#34; rules: - id: access_document (1) match: routes: - path: /document/:id (2) methods: [ GET, POST, DELETE ] forward_to: (3) host: upstream:8081 execute: - authenticator: jwt_auth (4) - authorizer: openfga_check (5) config: values: store_id: 01HSXG2XSZJMQG99EVXB4QQX8P (6) model_id: 01HSXG7TBQEJ7GBPKQR2VYH24G (7) relation: \u0026gt; (8) {{- if eq .Request.Method \u0026#34;GET\u0026#34; -}} reader {{- else if eq .Request.Method \u0026#34;POST\u0026#34; -}} creator {{- else if eq .Request.Method \u0026#34;DELETE\u0026#34; -}} deleter {{- else -}} unknown {{- end -}} object: \u0026gt; document:{{- .Request.URL.Captures.id -}} (9) - finalizer: create_jwt (10) - id: list_documents (11) match: routes: - path: /documents (12) methods: [ GET ] (14) forward_to: (13) host: upstream:8081 execute: (15) - authenticator: jwt_auth - contextualizer: openfga_list config: values: store_id: 01HSXG2XSZJMQG99EVXB4QQX8P model_id: 01HSXG7TBQEJ7GBPKQR2VYH24G relation: reader - finalizer: create_jwt config: claims: | {{ toJson .Outputs.openfga_list }} (16) 1 Our rule set consists of two rules. The first one has the id access_document 2 This rule should match urls of the following form /document/\u0026lt;id\u0026gt;, with id being the identifier of a document. 3 If the execution of the authentication \u0026amp; authorization pipeline was successful, the request should be forwarded to the upstream:8081 host. 4 The authentication \u0026amp; authorization pipeline starts with the reference to the previously defined authenticator jwt_auth 5 Next, we specify the openfga_check authorizer and also configure the rule specific settings 6 Replace the value here with the store id, you’ve received in step 6 7 Replace the value here with the authorization model id, you’ve received in step 7 8 Here, we set the relation depending on the used HTTP request method 9 Our object reference. We use the value captured by the wildcard named id. 10 Reference to the previously configured finalizer to create a JWT to be forwarded to our upstream service 11 This is our second rule. It has the id list_documents. 12 And matches any request of the form /documents 13 As the previous rule, this one forwards the request to the upstream:8081 host on successful completion of the authentication \u0026amp; authorization pipeline 14 Unlike the access_document rule, this one allows only HTTP GET methods for the matched urls. 15 The authentication \u0026amp; authorization pipeline is pretty similar to the previous rule. The main difference is the usage of the openfga_list contextualizer instead of the openfga_check authorizer and the reconfiguration of the create_jwt finalizer. As with the previous rule, replace the store_id and model_id with the values, you’ve received above. 16 Here, we reconfigure our finalizer to include the results from the openfga_list contextualizer into the created JWT. Update Relationship Tuples Having everything in place, time to configure the actual permissions. As with the previous steps, this one is based on Update Relationship Tuples from the official OpenFGA guide. So, let us give our user anne at least the read permission.\nIf you skip this step and directly continue with Use the Setup, you’ll always receive a 403 Forbidden response. Call the OpenFGA write endpoint as also described in Calling Write API To Add New Relationship Tuples to create a reader relationship between our user anne and the document with the id 1234. Replace the store id and the authorization model id with those, you’ve received while following the steps above:\ncurl -X POST http://127.0.0.1:8080/stores/\u0026lt;the store id from above\u0026gt;/write \\ -H \u0026#34;content-type: application/json\u0026#34; \\ -d \u0026#39;{ \u0026#34;authorization_model_id\u0026#34;: \u0026#34;\u0026lt;the authorization model id from above\u0026gt;\u0026#34;, \u0026#34;writes\u0026#34;: { \u0026#34;tuple_keys\u0026#34; : [ { \u0026#34;user\u0026#34;:\u0026#34;user:anne\u0026#34;, \u0026#34;relation\u0026#34;:\u0026#34;reader\u0026#34;, \u0026#34;object\u0026#34;:\u0026#34;document:1234\u0026#34; } ] } }\u0026#39; Verify anne has the required permissions\ncurl -X POST http://127.0.0.1:8080/stores/\u0026lt;the store id from above\u0026gt;/check \\ -H \u0026#34;content-type: application/json\u0026#34; \\ -d \u0026#39;{ \u0026#34;authorization_model_id\u0026#34;: \u0026#34;\u0026lt;the authorization model id from above\u0026gt;\u0026#34;, \u0026#34;tuple_key\u0026#34;: { \u0026#34;user\u0026#34;: \u0026#34;user:anne\u0026#34;, \u0026#34;relation\u0026#34;: \u0026#34;reader\u0026#34;, \u0026#34;object\u0026#34;: \u0026#34;document:1234\u0026#34; } }\u0026#39; You should receive the following response:\n{\u0026#34;allowed\u0026#34;:true, \u0026#34;resolution\u0026#34;:\u0026#34;\u0026#34;} Use the Setup We have now definitely everything in place to allow our user anne to at least read the document with the id 1234 and also list the documents anne has access to.\nTry executing the following command:\n$ curl -X GET -H \u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0yIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjcyMzUxODUsImlhdCI6MTcxMTg3NTE4NSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI1ZDJjM2E3OC1hM2Y5LTRlNmYtOTExYi0xZjZmZWQ5ODE3YTciLCJuYmYiOjE3MTE4NzUxODUsInN1YiI6ImFubmUifQ.wH7HOs-w8YbsOLJcZ9bHBuY5lCBZmYUhQGLJyEbePJZ_WlyR7aa0QmCc3Yx9JsSs3HDmnIbD2wUaFTe2rZWtqA\u0026#34; \\ 127.0.0.1:9090/document/1234 You should see an output similar to the one shown below. Since our upstream does just echo everything back it receives, it represents a successful response to read the document with the id 1234.\nHostname: 94e60bba8498 IP: 127.0.0.1 IP: 172.19.0.2 RemoteAddr: 172.19.0.4:43688 GET /admin HTTP/1.1 Host: upstream:8081 User-Agent: curl/8.2.1 Accept: */* Accept-Encoding: gzip Authorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2OTQ5MzAsImlhdCI6MTcxODY5NDYzMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJiNzgyZGE4YS1mMDFlLTRmYmUtYTlkZC04MzdiYzYzYzlhODUiLCJuYmYiOjE3MTg2OTQ2MzAsInN1YiI6ImFubmUifQ.xANlIPmRWdMraL_j0i-0cK4NVhqopzgSc5_u0m4Hyg4VAFQ3ZHuuap1ZD9hs8ZkBQGin9-vPsBeVrQr40OfAev7WKyNVPpIpmFBAU8fX15kXgVXox29kgBAcAM2b2W-w Forwarded: for=172.19.0.1;host=127.0.0.1:9090;proto=http Let us list the documents our user has access to\n$ curl -H \u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0yIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjcyMzUxODUsImlhdCI6MTcxMTg3NTE4NSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI1ZDJjM2E3OC1hM2Y5LTRlNmYtOTExYi0xZjZmZWQ5ODE3YTciLCJuYmYiOjE3MTE4NzUxODUsInN1YiI6ImFubmUifQ.wH7HOs-w8YbsOLJcZ9bHBuY5lCBZmYUhQGLJyEbePJZ_WlyR7aa0QmCc3Yx9JsSs3HDmnIbD2wUaFTe2rZWtqA\u0026#34; \\ 127.0.0.1:9090/documents You should again see an output similar to the one shown below. However, if you take a closer look at the JWT from the Authorization header by e.g. making use of https://www.jstoolset.com/jwt, you’ll see it contains also a list of documents anne has access to.\nHostname: 94e60bba8498 IP: 127.0.0.1 IP: 172.19.0.2 RemoteAddr: 172.19.0.4:43688 GET /admin HTTP/1.1 Host: upstream:8081 User-Agent: curl/8.2.1 Accept: */* Accept-Encoding: gzip Authorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2OTUwODEsImlhdCI6MTcxODY5NDc4MSwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJiNWRhMDg2OC0yNTFhLTRhZmEtODk4ZS1hZThlYzdkZjMyZDEiLCJuYmYiOjE3MTg2OTQ3ODEsIm9iamVjdHMiOlsiZG9jdW1lbnQ6MTIzNCJdLCJzdWIiOiJhbm5lIn0.GY-4oi75KV8jQz5SgMzVMG_-CcCSi9XpmRE934Uq-A326MBwTcFuHysSYmWNz85wwG5zti2Jijn1T8Vm2fpTVEgEE6qltB9caVQlVNGDyF3uAVdpq9NRgHDcru3-15oB Forwarded: for=172.19.0.1;host=127.0.0.1:9090;proto=http Try accessing a document with the id 1235 or delete a document using the DELETE HTTP verb. Useless :). Heimdall won’t let you through. But you can add new relations as you did in Update Relationship Tuples to allow anne accessing further documents, or delete, or modify existing documents. Try that.\nCleanup Just stop the environment with CTRL-C and delete the created files. If you started docker compose in the background, tear the environment down with\n$ docker compose down ","description":"This guide explains how to integrate heimdall with the OpenFGA, a scalable open source authorization system.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://openfga.dev\"\u003eOpenFGA\u003c/a\u003e is inspired by \u003ca href=\"https://zanzibar.academy/\"\u003eGoogle’s Zanzibar\u003c/a\u003e, Google’s Relationship Based Access Control system and allows easily implementing authorization for any kind of application relying on Role-Based Access Control with additional Attribute-Based Access Control capabilities.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis guide is based on the OpenFGA’s official \u003ca href=\"https://openfga.dev/docs/getting-started\"\u003eGetting Started\u003c/a\u003e guide and highlights the relevant differences. It mimics a RESTful document management API, allowing listing, creating, reading, updating, and deleting documents. The API consists of two endpoints:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/document/\u0026lt;id\u0026gt;\u003c/code\u003e with \u003ccode\u003eid\u003c/code\u003e being the id of the document and the HTTP verbs reflecting the actual operations. E.g. a \u003ccode\u003eGET /document/1234\u003c/code\u003e request should read the document with the id \u003ccode\u003e1234\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/documents\u003c/code\u003e which supports the HTTP \u003ccode\u003eGET\u003c/code\u003e verb only and allows the user to list the documents it can access.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe identity of the user will be taken from a JWT.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nEven this guide addresses OpenFGA, it actually covers integration with any ReBAC system, be it Ory’s \u003ca href=\"https://www.ory.sh/keto/\"\u003eKeto\u003c/a\u003e, \u003ca href=\"https://authzed.com/spicedb\"\u003eSpiceDB\u003c/a\u003e from AuthZed, or any other system inspired by Google’s Zanzibar.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo be able to follow this guide, you’ll need the following tools installed locally:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/install/\"\u003eDocker\u003c/a\u003e,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/compose/install/\"\u003edocker-compose\u003c/a\u003e, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea text editor of your choice.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configure_the_base_setup\"\u003eConfigure the Base Setup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a directory in which we’re going to create further directories and files required for the setup and switch to it.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a directory named \u003ccode\u003erules\u003c/code\u003e. We’ll add the heimdall rule to it after our setup is started.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a \u003ccode\u003edocker-compose.yaml\u003c/code\u003e file with the following contents\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edadrus/heimdall:dev\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtainer_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e9090:4455\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./heimdall-config.yaml:/etc/heimdall/config.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./rules:/etc/heimdall/rules:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./signer.pem:/etc/heimdall/signer.pem:ro\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eserve proxy -c /etc/heimdall/config.yaml --insecure\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eupstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003econtainous/whoami:latest\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtainer_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e--port=8081\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eopenfga\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga/openfga:latest\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtainer_name\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erun\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e8080:8080\u0026#34;\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eidp\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enginx:1.25.4\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./idp.nginx:/etc/nginx/nginx.conf:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./jwks.json:/var/www/nginx/jwks.json:ro\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines configure heimdall to use a config file, we’re going to configure next and a rule directory, we’ll add our rules to.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWe’re using the \u003ccode\u003e--insecure\u003c/code\u003e flag here to simplify our setup, which disables enforcement of some security settings you can learn about more \u003ca href=\"/docs/operations/security/#_defaults\"\u003ehere\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we define the \u0026#34;upstream\u0026#34; service, which just echoes back everything it receives.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAnd these lines configure our OpenFGA instance. It is the simplest setup, described in \u003ca href=\"https://openfga.dev/docs/getting-started/setup-openfga/docker\"\u003eSetup OpenFGA with Docker\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is an NGINX service, which mimics an IDP system and exposes an JWKS endpoint with key material, heimdall is going to use to validate the JWT you’re going to use.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a configuration file for heimdall, named \u003ccode\u003eheimdall-config.yaml\u003c/code\u003e with the following contents.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_auth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ejwks_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://idp:8080/.well-known/jwks\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003edemo_issuer\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_check\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://openfga:8080/stores/{{ .Values.store_id }}/check\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;authorization_model_id\u0026#34;: \u0026#34;{{ .Values.model_id }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;tuple_key\u0026#34;: {\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;relation\u0026#34;:\u0026#34;{{ .Values.relation }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;object\u0026#34;:\u0026#34;{{ .Values.object }}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.allowed == true \u003c/span\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003econtextualizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_list\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://openfga:8080/stores/{{ .Values.store_id }}/list-objects\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;authorization_model_id\u0026#34;: \u0026#34;{{ .Values.model_id }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;relation\u0026#34;:\u0026#34;{{ .Values.relation }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;type\u0026#34;:\u0026#34;document\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e \u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e(9)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/signer.pem\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eproviders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e(10)\u003c/b\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/rules\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis and the following lines define and configure the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authenticators/#_jwt\"\u003ejwt\u003c/a\u003e\u003c/code\u003e authenticator named \u003ccode\u003ejwt_auth\u003c/code\u003e. With the given configuration it will check whether a request contains an \u003ccode\u003eAuthorization\u003c/code\u003e header with a bearer token in JWT format and validate it using key material fetched from the JWKS endpoint.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we define and configure a \u003ccode\u003e\u003ca href=\"/docs/mechanisms/authorizers/#_remote\"\u003eremote\u003c/a\u003e\u003c/code\u003e authorizer named \u003ccode\u003eopenfga_check\u003c/code\u003e, which we’re going to use for the actual authorization purposes in our rules.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we define the endpoint to be used for the authorization checks. Most probably, you’ll want to hard code your OpenFGA model id. Since, we’re going to create the model, when we start our setup, we’ll reference it in our rule via \u003ccode\u003estore_id\u003c/code\u003e.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWe use a very simple \u003ccode\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eendpoint\u003c/a\u003e\u003c/code\u003e configuration here by just specifying the actual url. If required, you can specify API keys, and many more. Take a look at the linked documentation of this property.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is the definition of our payload to be sent to the check endpoint. As we don’t know the model id as well, we’ll configure it in our rule. The user will be taken from the \u003ccode\u003eSubject\u003c/code\u003e create by heimdall, and the relation and object will be specified in our rule.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eIn case of a successful response, the response from the check endpoint will look like \u003ccode\u003e{\u0026#34;allowed\u0026#34;: true}\u003c/code\u003e. Otherwise, it will be \u003ccode\u003e{\u0026#34;allowed\u0026#34;: false}\u003c/code\u003e. With the expression here, we perform the required verification.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere we define and configure a \u003ccode\u003e\u003ca href=\"/docs/mechanisms/contextualizers/#_generic\"\u003egeneric\u003c/a\u003e\u003c/code\u003e contextualizer named \u003ccode\u003eopenfga_list\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAs with the authorization mechanism, defined above, here we configure the endpoint to list the allowed objects.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe payload configuration used while communicating to the configured endpoint.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e9\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe following two lines define the \u003ccode\u003e\u003ca href=\"/docs/mechanisms/finalizers/#_jwt\"\u003ejwt\u003c/a\u003e\u003c/code\u003e finalizer. With the given configuration, it will create a jwt out of the subject object with standard claims and set the \u003ccode\u003esub\u003c/code\u003e claim to the value of subject’s ID.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e10\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe last few lines of the configure the \u003ccode\u003e\u003ca href=\"/docs/rules/providers/#_filesystem\"\u003efile_system\u003c/a\u003e\u003c/code\u003e provider, which allows loading of regular rules from the file system.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a file, named \u003ccode\u003esigner.pem\u003c/code\u003e with the following content. This is our key store with a private key, you’ve seen in the configuration above.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"s\"\u003e-----BEGIN EC PRIVATE KEY-----\u003c/span\u003e\n\u003cspan class=\"s\"\u003eMIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy\u003c/span\u003e\n\u003cspan class=\"s\"\u003e1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI\u003c/span\u003e\n\u003cspan class=\"s\"\u003ezlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X\u003c/span\u003e\n\u003cspan class=\"s\"\u003eXVwR/5tokqFVrFxt/5c1x7VdccF4nNM=\u003c/span\u003e\n\u003cspan class=\"s\"\u003e-----END EC PRIVATE KEY-----\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nDo not use it for purposes beyond this tutorial!\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eConfigure NGINX to expose a static endpoint serving a JWKS document under the \u003ccode\u003e.well-known\u003c/code\u003e path, so heimdall is able to verify the JWT, we’re going to use. Create a file named \u003ccode\u003eidp.nginx\u003c/code\u003e with the following content:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eworker_processes 1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\nuser nginx\u003cspan class=\"p\"\u003e;\u003c/span\u003e\npid /var/run/nginx.pid\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\nevents \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n worker_connections 1024\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\nhttp \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n keepalive_timeout 65\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n server \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n listen 8080\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n location /.well-known/jwks \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n default_type application/json\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n root /var/www/nginx\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n try_files /jwks.json \u003cspan class=\"o\"\u003e=\u003c/span\u003e404\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition, create a file named \u003ccode\u003ejwks.json\u003c/code\u003e with the public key required to verify the tokens we’re going to use.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;keys\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;use\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;sig\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;kty\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;EC\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;kid\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;key-2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;crv\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;P-256\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;alg\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;ES256\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;x\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;NnU0iWRq7szZP_8Ir3D4BShUEtcW1dHpuvlCgB6ecE0\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;y\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;X71tZm51ovUPFNKE0bsi5XF-FtIykEfk1O83EHNkSdo\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_create_authorization_model_rules\"\u003eCreate Authorization Model \u0026amp; Rules\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe static configuration of our services is in place. Let us now create the actual authorization model and based on it the required heimdall rules.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eStart our setup with \u003ccode\u003edocker compose up\u003c/code\u003e and wait until all services are up and running.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate the OpenFGA store as also described in \u003ca href=\"https://openfga.dev/docs/getting-started/create-store\"\u003eCreate Store\u003c/a\u003e with\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003ecurl \u003cspan class=\"nt\"\u003e-X\u003c/span\u003e POST http://127.0.0.1:8080/stores \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;content-type: application/json\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-d\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;{\u0026#34;name\u0026#34;: \u0026#34;FGA Demo Store\u0026#34;}\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis call should result in an output similar to\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;01HSXG2XSZJMQG99EVXB4QQX8P\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;FGA Demo Store\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;created_at\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;2024-03-26T13:44:37.439559338Z\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;updated_at\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;2024-03-26T13:44:37.439559338Z\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNote or write down the value of the store \u003ccode\u003eid\u003c/code\u003e returned.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eConfigure the authorization model as also described in \u003ca href=\"https://openfga.dev/docs/getting-started/configure-model\"\u003eConfigure Model\u003c/a\u003e with\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003ecurl \u003cspan class=\"nt\"\u003e-X\u003c/span\u003e POST http://127.0.0.1:8080/stores/\u0026lt;the \u003cspan class=\"nb\"\u003eid \u003c/span\u003efrom above\u0026gt;/authorization-models \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;content-type: application/json\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-d\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;{\u0026#34;schema_version\u0026#34;:\u0026#34;1.1\u0026#34;,\u0026#34;type_definitions\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;},{\u0026#34;type\u0026#34;:\u0026#34;document\u0026#34;,\u0026#34;relations\u0026#34;:{\u0026#34;reader\u0026#34;:{\u0026#34;this\u0026#34;:{}},\u0026#34;writer\u0026#34;:{\u0026#34;this\u0026#34;:{}},\u0026#34;owner\u0026#34;:{\u0026#34;this\u0026#34;:{}}},\u0026#34;metadata\u0026#34;:{\u0026#34;relations\u0026#34;:{\u0026#34;reader\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]},\u0026#34;writer\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]},\u0026#34;owner\u0026#34;:{\u0026#34;directly_related_user_types\u0026#34;:[{\u0026#34;type\u0026#34;:\u0026#34;user\u0026#34;}]}}}}]}\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis call should result in an output similar to\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;authorization_model_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;01HSXG7TBQEJ7GBPKQR2VYH24G\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNote or write down the value of \u003ccode\u003eauthorization_model_id\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eLet us now create a rule set for heimdall. Create a file named \u003ccode\u003edemo.yaml\u003c/code\u003e with the following contents in the \u003ccode\u003erules\u003c/code\u003e directory\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_document\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/document/:id\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"nv\"\u003eGET\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"nv\"\u003ePOST\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"nv\"\u003eDELETE\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_auth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_check\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003estore_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e01HSXG2XSZJMQG99EVXB4QQX8P\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003emodel_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e01HSXG7TBQEJ7GBPKQR2VYH24G\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"na\"\u003erelation\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e\u0026gt;\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n \u003cspan class=\"s\"\u003e{{- if eq .Request.Method \u0026#34;GET\u0026#34; -}} reader\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{- else if eq .Request.Method \u0026#34;POST\u0026#34; -}} creator\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{- else if eq .Request.Method \u0026#34;DELETE\u0026#34; -}} deleter\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{- else -}} unknown\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{- end -}}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eobject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"s\"\u003edocument:{{- .Request.URL.Captures.id -}} \u003c/span\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e(9)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e \u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e(10)\u003c/b\u003e\n\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003elist_documents\u003c/span\u003e \u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e(11)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/documents\u003c/span\u003e \u003ci class=\"conum\" data-value=\"12\"\u003e\u003c/i\u003e\u003cb\u003e(12)\u003c/b\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"nv\"\u003eGET\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e \u003ci class=\"conum\" data-value=\"14\"\u003e\u003c/i\u003e\u003cb\u003e(14)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"13\"\u003e\u003c/i\u003e\u003cb\u003e(13)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"15\"\u003e\u003c/i\u003e\u003cb\u003e(15)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_auth\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_list\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003estore_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e01HSXG2XSZJMQG99EVXB4QQX8P\u003c/span\u003e\n \u003cspan class=\"na\"\u003emodel_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e01HSXG7TBQEJ7GBPKQR2VYH24G\u003c/span\u003e\n \u003cspan class=\"na\"\u003erelation\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ereader\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclaims\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ toJson .Outputs.openfga_list }} \u003c/span\u003e\u003ci class=\"conum\" data-value=\"16\"\u003e\u003c/i\u003e\u003cb\u003e(16)\u003c/b\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eOur rule set consists of two rules. The first one has the id \u003ccode\u003eaccess_document\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis rule should match urls of the following form \u003ccode\u003e/document/\u0026lt;id\u0026gt;\u003c/code\u003e, with id being the identifier of a document.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eIf the execution of the authentication \u0026amp; authorization pipeline was successful, the request should be forwarded to the \u003ccode\u003eupstream:8081\u003c/code\u003e host.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe authentication \u0026amp; authorization pipeline starts with the reference to the previously defined authenticator \u003ccode\u003ejwt_auth\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eNext, we specify the \u003ccode\u003eopenfga_check\u003c/code\u003e authorizer and also configure the rule specific settings\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eReplace the value here with the store id, you’ve received in step 6\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eReplace the value here with the authorization model id, you’ve received in step 7\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we set the relation depending on the used HTTP request method\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e9\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eOur object reference. We use the value captured by the wildcard named \u003ccode\u003eid\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e10\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eReference to the previously configured finalizer to create a JWT to be forwarded to our upstream service\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e11\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis is our second rule. It has the id \u003ccode\u003elist_documents\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"12\"\u003e\u003c/i\u003e\u003cb\u003e12\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAnd matches any request of the form \u003ccode\u003e/documents\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"13\"\u003e\u003c/i\u003e\u003cb\u003e13\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eAs the previous rule, this one forwards the request to the \u003ccode\u003eupstream:8081\u003c/code\u003e host on successful completion of the authentication \u0026amp; authorization pipeline\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"14\"\u003e\u003c/i\u003e\u003cb\u003e14\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eUnlike the \u003ccode\u003eaccess_document\u003c/code\u003e rule, this one allows only HTTP GET methods for the matched urls.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"15\"\u003e\u003c/i\u003e\u003cb\u003e15\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe authentication \u0026amp; authorization pipeline is pretty similar to the previous rule. The main difference is the usage of the \u003ccode\u003eopenfga_list\u003c/code\u003e contextualizer instead of the \u003ccode\u003eopenfga_check\u003c/code\u003e authorizer and the reconfiguration of the \u003ccode\u003ecreate_jwt\u003c/code\u003e finalizer. As with the previous rule, replace the \u003ccode\u003estore_id\u003c/code\u003e and \u003ccode\u003emodel_id\u003c/code\u003e with the values, you’ve received above.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"16\"\u003e\u003c/i\u003e\u003cb\u003e16\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we reconfigure our finalizer to include the results from the \u003ccode\u003eopenfga_list\u003c/code\u003e contextualizer into the created JWT.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_update_relationship_tuples\"\u003eUpdate Relationship Tuples\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHaving everything in place, time to configure the actual permissions. As with the previous steps, this one is based on \u003ca href=\"https://openfga.dev/docs/getting-started/update-tuples\"\u003eUpdate Relationship Tuples\u003c/a\u003e from the official OpenFGA guide. So, let us give our user \u003ccode\u003eanne\u003c/code\u003e at least the \u003ccode\u003eread\u003c/code\u003e permission.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you skip this step and directly continue with \u003ca href=\"#_use_the_setup\"\u003eUse the Setup\u003c/a\u003e, you’ll always receive a \u003ccode\u003e403 Forbidden\u003c/code\u003e response.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eCall the OpenFGA write endpoint as also described in \u003ca href=\"https://openfga.dev/docs/getting-started/update-tuples#02-calling-write-api-to-add-new-relationship-tuples\"\u003eCalling Write API To Add New Relationship Tuples\u003c/a\u003e to create a reader relationship between our user \u003ccode\u003eanne\u003c/code\u003e and the document with the id \u003ccode\u003e1234\u003c/code\u003e. Replace the store id and the authorization model id with those, you’ve received while following the steps above:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003ecurl \u003cspan class=\"nt\"\u003e-X\u003c/span\u003e POST http://127.0.0.1:8080/stores/\u0026lt;the store \u003cspan class=\"nb\"\u003eid \u003c/span\u003efrom above\u0026gt;/write \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;content-type: application/json\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-d\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;{\n \u0026#34;authorization_model_id\u0026#34;: \u0026#34;\u0026lt;the authorization model id from above\u0026gt;\u0026#34;,\n \u0026#34;writes\u0026#34;: {\n \u0026#34;tuple_keys\u0026#34; : [\n {\n \u0026#34;user\u0026#34;:\u0026#34;user:anne\u0026#34;,\n \u0026#34;relation\u0026#34;:\u0026#34;reader\u0026#34;,\n \u0026#34;object\u0026#34;:\u0026#34;document:1234\u0026#34;\n }\n ]\n }\n }\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eVerify \u003ccode\u003eanne\u003c/code\u003e has the required permissions\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003ecurl \u003cspan class=\"nt\"\u003e-X\u003c/span\u003e POST http://127.0.0.1:8080/stores/\u0026lt;the store \u003cspan class=\"nb\"\u003eid \u003c/span\u003efrom above\u0026gt;/check \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;content-type: application/json\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-d\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;{\n \u0026#34;authorization_model_id\u0026#34;: \u0026#34;\u0026lt;the authorization model id from above\u0026gt;\u0026#34;,\n \u0026#34;tuple_key\u0026#34;: {\n \u0026#34;user\u0026#34;: \u0026#34;user:anne\u0026#34;,\n \u0026#34;relation\u0026#34;: \u0026#34;reader\u0026#34;,\n \u0026#34;object\u0026#34;: \u0026#34;document:1234\u0026#34;\n }\n }\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou should receive the following response:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;allowed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;resolution\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_use_the_setup\"\u003eUse the Setup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWe have now definitely everything in place to allow our user \u003ccode\u003eanne\u003c/code\u003e to at least read the document with the id \u003ccode\u003e1234\u003c/code\u003e and also list the documents \u003ccode\u003eanne\u003c/code\u003e has access to.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eTry executing the following command:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl \u003cspan class=\"nt\"\u003e-X\u003c/span\u003e GET \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0yIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjcyMzUxODUsImlhdCI6MTcxMTg3NTE4NSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI1ZDJjM2E3OC1hM2Y5LTRlNmYtOTExYi0xZjZmZWQ5ODE3YTciLCJuYmYiOjE3MTE4NzUxODUsInN1YiI6ImFubmUifQ.wH7HOs-w8YbsOLJcZ9bHBuY5lCBZmYUhQGLJyEbePJZ_WlyR7aa0QmCc3Yx9JsSs3HDmnIbD2wUaFTe2rZWtqA\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n 127.0.0.1:9090/document/1234\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou should see an output similar to the one shown below. Since our upstream does just echo everything back it receives, it represents a successful response to read the document with the id \u003ccode\u003e1234\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eHostname: 94e60bba8498\nIP: 127.0.0.1\nIP: 172.19.0.2\nRemoteAddr: 172.19.0.4:43688\nGET /admin HTTP/1.1\nHost: upstream:8081\nUser-Agent: curl/8.2.1\nAccept: \u003cspan class=\"k\"\u003e*\u003c/span\u003e/\u003cspan class=\"k\"\u003e*\u003c/span\u003e\nAccept-Encoding: \u003cspan class=\"nb\"\u003egzip\n\u003c/span\u003eAuthorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2OTQ5MzAsImlhdCI6MTcxODY5NDYzMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJiNzgyZGE4YS1mMDFlLTRmYmUtYTlkZC04MzdiYzYzYzlhODUiLCJuYmYiOjE3MTg2OTQ2MzAsInN1YiI6ImFubmUifQ.xANlIPmRWdMraL_j0i-0cK4NVhqopzgSc5_u0m4Hyg4VAFQ3ZHuuap1ZD9hs8ZkBQGin9-vPsBeVrQr40OfAev7WKyNVPpIpmFBAU8fX15kXgVXox29kgBAcAM2b2W-w\nForwarded: \u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e172.19.0.1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003ehost\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e127.0.0.1:9090\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003eproto\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttp\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eLet us list the documents our user has access to\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ecurl \u003cspan class=\"nt\"\u003e-H\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6ImtleS0yIiwidHlwIjoiSldUIn0.eyJleHAiOjIwMjcyMzUxODUsImlhdCI6MTcxMTg3NTE4NSwiaXNzIjoiZGVtb19pc3N1ZXIiLCJqdGkiOiI1ZDJjM2E3OC1hM2Y5LTRlNmYtOTExYi0xZjZmZWQ5ODE3YTciLCJuYmYiOjE3MTE4NzUxODUsInN1YiI6ImFubmUifQ.wH7HOs-w8YbsOLJcZ9bHBuY5lCBZmYUhQGLJyEbePJZ_WlyR7aa0QmCc3Yx9JsSs3HDmnIbD2wUaFTe2rZWtqA\u0026#34;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n 127.0.0.1:9090/documents\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou should again see an output similar to the one shown below. However, if you take a closer look at the JWT from the \u003ccode\u003eAuthorization\u003c/code\u003e header by e.g. making use of \u003ca href=\"https://www.jstoolset.com/jwt\" class=\"bare\"\u003ehttps://www.jstoolset.com/jwt\u003c/a\u003e, you’ll see it contains also a list of documents \u003ccode\u003eanne\u003c/code\u003e has access to.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eHostname: 94e60bba8498\nIP: 127.0.0.1\nIP: 172.19.0.2\nRemoteAddr: 172.19.0.4:43688\nGET /admin HTTP/1.1\nHost: upstream:8081\nUser-Agent: curl/8.2.1\nAccept: \u003cspan class=\"k\"\u003e*\u003c/span\u003e/\u003cspan class=\"k\"\u003e*\u003c/span\u003e\nAccept-Encoding: \u003cspan class=\"nb\"\u003egzip\n\u003c/span\u003eAuthorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MTg2OTUwODEsImlhdCI6MTcxODY5NDc4MSwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJiNWRhMDg2OC0yNTFhLTRhZmEtODk4ZS1hZThlYzdkZjMyZDEiLCJuYmYiOjE3MTg2OTQ3ODEsIm9iamVjdHMiOlsiZG9jdW1lbnQ6MTIzNCJdLCJzdWIiOiJhbm5lIn0.GY-4oi75KV8jQz5SgMzVMG_-CcCSi9XpmRE934Uq-A326MBwTcFuHysSYmWNz85wwG5zti2Jijn1T8Vm2fpTVEgEE6qltB9caVQlVNGDyF3uAVdpq9NRgHDcru3-15oB\nForwarded: \u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e172.19.0.1\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003ehost\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e127.0.0.1:9090\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"nv\"\u003eproto\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttp\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eTry accessing a document with the id \u003ccode\u003e1235\u003c/code\u003e or delete a document using the \u003ccode\u003eDELETE\u003c/code\u003e HTTP verb. Useless :). Heimdall won’t let you through. But you can add new relations as you did in \u003ca href=\"#_update_relationship_tuples\"\u003eUpdate Relationship Tuples\u003c/a\u003e to allow \u003ccode\u003eanne\u003c/code\u003e accessing further documents, or delete, or modify existing documents. Try that.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cleanup\"\u003eCleanup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eJust stop the environment with \u003ccode\u003eCTRL-C\u003c/code\u003e and delete the created files. If you started docker compose in the background, tear the environment down with\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003edocker compose down\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","Authorization Services"],"tags":null,"title":"Integration with OpenFGA","url":"/guides/authz/openfga/"},{"categories":null,"content":" By the end of this guide, you’ll have a functional setup where heimdall uses Keycloak to authenticate users and route requests based on their authentication status and roles for role-based access control.\nAlthough this guide uses Keycloak as identity provider (IDP), you can achieve the same results with Zitadel, Boruta, or any other OpenID Connect-compatible IDP.\nOverview In this guide, we’ll set up a Docker Compose environment where heimdall secures services and controls access to specific endpoints:\n/ - This endpoint is open to everyone.\n/user - Accessible only to authenticated users.\n/admin - Accessible only to users with the admin role.\nThere are also some further endpoints, which you’ll learn about during the setup.\nTechnically, the setup includes:\ncontainous/whoami - A service that echoes back everything it receives, simulating our main service with endpoints mentioned above.\nKeycloak - Our identity provider.\nOAuth2-Proxy - Handles the Authorization Code Grant flow for the actual user login.\nheimdall - Manages everything to enforce the requirements outlined above.\nPrerequisites To be able to follow this guide you need the following tools installed locally:\nDocker,\ndocker-compose, and\na text editor of your choice.\nConfigure the Base Setup Create a directory for the configuration files we’ll be using (referred to as the root directory in this guide). Inside this root directory, create two additional directories named rules and initdb. The former will be used for heimdall rules and the latter for DB initialization scripts.\nCreate a config file for heimdall named heimdall-config.yaml with the following contents in the root directory:\nlog: (1) level: debug tracing: enabled: false metrics: enabled: false mechanisms: (2) authenticators: - id: deny_all (3) type: unauthorized - id: anon (4) type: anonymous - id: auth (5) type: generic config: identity_info_endpoint: http://oauth2-proxy:4180/oauth2/userinfo authentication_data_source: - cookie: SESSION forward_cookies: - SESSION subject: id: \u0026#34;user\u0026#34; authorizers: - id: cel (6) type: cel config: expressions: - expression: \u0026#34;true == false\u0026#34; finalizers: - id: create_jwt (7) type: jwt config: signer: key_store: path: /etc/heimdall/signer.pem claims: | {{- dict \u0026#34;attrs\u0026#34; .Subject.Attributes | toJson -}} - id: noop (8) type: noop error_handlers: (9) - id: redirect_to_idp type: redirect config: to: http://127.0.0.1:9090/oauth2/start?rd={{ .Request.URL | urlenc }} - id: redirect_to_error_page type: redirect config: to: https://www.google.com/search?q=access+denied\u0026amp;udm=2 default_rule: (10) execute: - authenticator: deny_all - finalizer: create_jwt on_error: - error_handler: redirect_to_error_page if: | type(Error) in [authorization_error, authentication_error] \u0026amp;\u0026amp; Request.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;) providers: (11) file_system: src: /etc/heimdall/rules watch: true 1 By default, heimdall emits logs on error level, but to better understand its operations, we’re setting the log level to debug. This way, you’ll see not only the results of rule executions (which is what you would see if we set the log level to info), but also detailed information about what’s happening within each rule. We’re also disabling tracing and metrics collection to avoid errors related to the missing OTEL agent, which is used by default. For more details on logging and other observability options, see the Observability chapter. 2 We define our catalogue of mechanisms for use in our default rule and upstream service-specific rules. 3 These lines define the unauthorized authenticator, named deny_all, which rejects all requests. 4 These lines define the anonymous authenticator, named anon, which allows all requests and creates a subject with the ID set to anonymous. More information about subjects and other objects can be found here. 5 These and the following lines set up the generic authenticator, named auth. This configuration checks if a request includes a Cookie named SESSION, and then sends it to the http://oauth2-proxy:4180/oauth2/userinfo endpoint to get user information. If successful, heimdall extracts the user identifier from the user property in the response. If there’s an error (e.g. the SESSION cookie is not present or the response from the OAuth2-Proxy contains an error), an authentication error is triggered. 6 These lines define a cel authorizer that is configured to always fail. We’ll improve this in our upstream-specific rule. 7 These lines define the jwt finalizer. It creates a JWT from the subject object with standard claims, setting the sub claim to the subject’s ID. The key for signing the JWT comes from a key store we’ll configure later. 8 These two lines define the noop finalizer, which we’ll use for public endpoints. 9 Here, we set up two redirect error handlers: one redirects to the /oauth2/start endpoint with a deep link to the current URL, and the other redirects to Google with the search query \u0026#34;access denied\u0026#34;. 10 With all mechanisms defined, we configure our first rule - the default rule. This rule applies if no other rules match the request and serves as a base for defining regular (upstream service-specific) rules as well. It sets up a default authentication \u0026amp; authorization pipeline that rejects all requests using the deny_all authenticator. This rejection triggers the redirect_to_error_page error handler. If a regular rule overrides this authenticator, a JWT is created using the jwt finalizer. 11 The last few lines configure the file_system provider, which loads regular rules from the file system and watches for changes. This allows you to modify the rules while testing. Create a file named signer.pem and add the following content to it. This file should also be placed in the root directory and will act as our key store, containing the private key referenced in the configuration above.\n-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy 1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI zlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X XVwR/5tokqFVrFxt/5c1x7VdccF4nNM= -----END EC PRIVATE KEY----- Do not use it for purposes beyond this tutorial! Next, we’ll create rules for our main service - the one exposing /, /user and the /admin endpoints. To do this, create a file named upstream-rules.yaml in the rules directory with the following content:\nversion: \u0026#34;1alpha4\u0026#34; rules: - id: upstream:public (1) match: routes: - path: / - path: /favicon.ico forward_to: host: upstream:8081 execute: - authenticator: anon - finalizer: noop - id: upstream:protected (2) match: routes: - path: /user - path: /admin forward_to: host: upstream:8081 execute: - authenticator: auth - authorizer: cel if: Request.URL.Path == \u0026#39;/admin\u0026#39; config: expressions: - expression: | has(Subject.Attributes.groups) \u0026amp;\u0026amp; \u0026#34;role:admin\u0026#34; in Subject.Attributes.groups message: User is not admin on_error: - error_handler: redirect_to_idp if: | type(Error) == authentication_error \u0026amp;\u0026amp; Request.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;) - error_handler: redirect_to_error_page if: | type(Error) == authorization_error \u0026amp;\u0026amp; Request.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;) 1 This first rule is for the / endpoint. It instructs heimdall to pass requests to this endpoint directly through to our upstream service. 2 The second rule ensures that the /user endpoint is only accessible to authenticated users, while the /admin endpoint is only accessible to users with the admin role configured in our IDP. Next, we’ll create a rule for the OAuth2-Proxy, placed behind heimdall and publicly exposing only certain endpoints. Create a new file named oauth2-proxy-rules.yaml in the rules directory with the following content:\nversion: \u0026#34;1alpha4\u0026#34; rules: - id: oauth2-proxy:public match: routes: - path: /oauth2/start - path: /oauth2/callback forward_to: host: oauth2-proxy:4180 execute: - authenticator: anon - finalizer: noop Next, we’ll create a database initialization script to set up a database for Keycloak. In the initdb directory, create a file named initdb.sh with the following content, and make it executable by running chmod +x initdb.sh:\n#!/bin/bash set -e psql -v ON_ERROR_STOP=1 --username \u0026#34;$POSTGRES_USER\u0026#34; \u0026lt;\u0026lt;-EOSQL CREATE USER keycloak WITH PASSWORD \u0026#39;keycloak\u0026#39;; CREATE DATABASE keycloak OWNER keycloak; EOSQL Now, let’s bring everything together using a Docker Compose file. Create a file named docker-compose.yaml in the root directory with the following content:\nservices: heimdall: (1) image: dadrus/heimdall:dev ports: - \u0026#34;9090:4455\u0026#34; command: serve proxy --c /etc/heimdall/config.yaml --insecure volumes: - ./heimdall-config.yaml:/etc/heimdall/config.yaml:ro - ./rules:/etc/heimdall/rules:ro - ./signer.pem:/etc/heimdall/signer.pem:ro upstream: (2) image: containous/whoami:latest command: --port=8081 oauth2-proxy: (3) depends_on: - keycloak image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0-amd64 command: - --http-address - 0.0.0.0:4180 environment: OAUTH2_PROXY_CLIENT_ID: placeholder (4) OAUTH2_PROXY_CLIENT_SECRET: placeholder OAUTH2_PROXY_REDIRECT_URL: http://127.0.0.1:9090/oauth2/callback (5) OAUTH2_PROXY_PROVIDER: keycloak-oidc OAUTH2_PROXY_SKIP_PROVIDER_BUTTON: true OAUTH2_PROXY_COOKIE_SECRET: VerySecure!!!!!! OAUTH2_PROXY_COOKIE_NAME: SESSION OAUTH2_PROXY_WHITELIST_DOMAINS: 127.0.0.1:9090 OAUTH2_PROXY_OIDC_ISSUER_URL: http://keycloak:8080/realms/test (6) OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL: true (7) OAUTH2_PROXY_EMAIL_DOMAINS: \u0026#39;*\u0026#39; OAUTH2_PROXY_OIDC_EXTRA_AUDIENCES: account (8) OAUTH2_PROXY_LOGIN_URL: http://127.0.0.1:8080/realms/test/protocol/openid-connect/auth (9) OAUTH2_PROXY_OIDC_JWKS_URL: http://keycloak:8080/realms/test/protocol/openid-connect/certs OAUTH2_PROXY_REDEEM_URL: http://keycloak:8080/realms/test/protocol/openid-connect/token OAUTH2_PROXY_INSECURE_OIDC_SKIP_ISSUER_VERIFICATION: true OAUTH2_PROXY_SKIP_OIDC_DISCOVERY: true keycloak: (10) image: quay.io/keycloak/keycloak:25.0.4 command: [ \u0026#34;start-dev\u0026#34;, \u0026#34;--http-port\u0026#34;, \u0026#34;8080\u0026#34; ] ports: - \u0026#34;8080:8080\u0026#34; environment: KC_HOSTNAME: 127.0.0.1 KC_HOSTNAME_PORT: 8080 KC_HOSTNAME_STRICT_BACKCHANNEL: \u0026#34;true\u0026#34; KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin KC_HEALTH_ENABLED: \u0026#34;true\u0026#34; KC_LOG_LEVEL: info KC_DB_URL_HOST: postgresql KC_DB: postgres KC_DB_USERNAME: keycloak KC_DB_PASSWORD: keycloak depends_on: - postgresql postgresql: (11) image: postgres:13.11 volumes: - type: volume source: postgres-db target: /var/lib/postgresql/data read_only: false - ./initdb:/docker-entrypoint-initdb.d environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres volumes: postgres-db: 1 Here, we configure heimdall to use the previously defined configuration. We’re using the --insecure flag here to simplify our setup, which disables enforcement of some security settings you can learn about more here. 2 This section sets up the main service that we’ll be protecting. 3 This section defines the OAuth2-Proxy configuration, which heimdall will use to handle the Authorization Code Grant flow and manage the authentication session with a SESSION cookie. 4 The client ID and client secret values are placeholders. We will configure these in Keycloak. 5 Since the redirect URI, exposed as /oauth2/callback, is behind heimdall, we use the publicly accessible endpoint here. 6 The URL of the issuer that OAuth2-Proxy will use. We’ll create a corresponding realm in Keycloak to match this configuration. 7 The following two lines are required as we don’t want keycloak to verify the email addresses of the users we’ll be creating, and we want to allow any email domain. 8 To avoid creating a mapper to let Keycloak set a proper aud claim value, we allow the usage of account audience set by Keycloak by default. 9 These lines are only required as Keycloak is part of our docker compose setup, and we have to use different domain names while communicating with it. 10 This section sets up Keycloak. 11 Finally, this section configures our database. Create a Realm and a Client in Keycloak With the above configuration in place, follow these steps to start Keycloak and the database, initialize both, and create the OAuth2-Proxy client:\nIn the root directory, run docker compose up postgresql keycloak. Wait until the database is initialized and Keycloak has started.\nOpen your browser and go to http://127.0.0.1:8080. Log in using the admin credentials (both the username and password are set to admin in our setup).\nCreate a Realm named test. For detailed instructions, refer to the Keycloak documentation on creating a realm.\nWithin the test realm, create an OpenID Client. Follow the Keycloak documentation on creating an OIDC client. Enable \u0026#34;Client authentication\u0026#34; and \u0026#34;Standard Flow\u0026#34;, set http://127.0.0.1:9090/oauth2/callback as the \u0026#34;Valid Redirect URI\u0026#34; and http://127.0.0.1:9090/ as the \u0026#34;Home URL\u0026#34; and \u0026#34;Valid post logout redirect URIs\u0026#34; and note the \u0026#34;Client ID\u0026#34; and \u0026#34;Client Secret\u0026#34; (later can be found under the \u0026#34;Credentials\u0026#34; tab after completing the client creation wizard); we will use these to complete the OAuth2-Proxy configuration in our Docker Compose file.\nStop the docker compose setup with CTRL-C.\nUpdate OAuth2-Proxy Configuration We can now finalize the configuration and use the proper client id and secret for OAuth2-Proxy\nUpdate the OAUTH2_PROXY_CLIENT_ID and OAUTH2_PROXY_CLIENT_SECRET in the configuration of the OAuth2-Proxy in the docker compose file with the \u0026#34;Client ID\u0026#34; and \u0026#34;Client Secret\u0026#34; values from Keycloak\nUse the Setup We now have almost everything set up. The final step is to create a few users, including at least one with the admin role assigned.\nIn the root directory, run docker compose up. Wait until all services are up and running.\nOpen your browser and navigate to http://127.0.0.1:8080. Log in using the admin credentials (both username and password are set to admin).\nSelect the test realm and create an admin group with a role named admin assigned to it. For guidance, refer to the Keycloak documentation on creating Groups and Roles.\nCreate several users following the Keycloak documentation on managing users, and assign some of them to the admin group. Disable email verification during user creation to avoid sending verification emails to potentially non-existent addresses.\nNow, let’s test the setup:\nNavigate to http://127.0.0.1:9090/. You should see some text similar to the one shown below. This text is the response from our upstream service, which echoes back everything the browser sends in its request.\nHostname: 39f1815dd8ac IP: 127.0.0.1 IP: ::1 IP: 172.31.0.3 RemoteAddr: 172.31.0.2:37908 GET / HTTP/1.1 Host: upstream:8081 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8 Accept-Encoding: gzip, deflate, br, zstd Accept-Language: de,en-US;q=0.7,en;q=0.3 Dnt: 1 Forwarded: for=172.31.0.1;host=127.0.0.1:9090;proto=http Priority: u=0, i Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: none Sec-Fetch-User: ?1 Upgrade-Insecure-Requests: 1 X-Trp-Catalog: de Attempt to access the http://127.0.0.1:9090/user endpoint. You should be redirected to the Keycloak login page. Log in with any of the users you configured. After logging in, you should be redirected back to http://127.0.0.1:9090/user, where you’ll see some text similar to the one shown below. This indicates that the request hit the /user endpoint of our upstream service. You should also see a JWT token in the Authorization header, which is the result of the JWT finalizer we configured.\nHostname: 39f1815dd8ac IP: 127.0.0.1 IP: ::1 IP: 172.31.0.3 RemoteAddr: 172.31.0.2:37908 GET /user HTTP/1.1 Host: upstream:8081 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8 Accept-Encoding: gzip, deflate, br, zstd Accept-Language: de,en-US;q=0.7,en;q=0.3 Authorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJhdHRycyI6eyJlbWFpbCI6InRlc3QxQGV4YW1wbGUuY29tIiwiZ3JvdXBzIjpbInJvbGU6ZGVmYXVsdC1yb2xlcy10ZXN0Iiwicm9sZTpvZmZsaW5lX2FjY2VzcyIsInJvbGU6YWRtaW4iLCJyb2xlOnVtYV9hdXRob3JpemF0aW9uIiwicm9sZTphY2NvdW50Om1hbmFnZS1hY2NvdW50Iiwicm9sZTphY2NvdW50Om1hbmFnZS1hY2NvdW50LWxpbmtzIiwicm9sZTphY2NvdW50OnZpZXctcHJvZmlsZSJdLCJwcmVmZXJyZWRVc2VybmFtZSI6InRlc3QxIiwidXNlciI6IjQ5ZWE3Mjk3LWI0NzgtNDcxNC05NjM2LWQ5ZTk3ZmVkZmNhOSJ9LCJleHAiOjE3MjY0NjkyMTAsImlhdCI6MTcyNjQ2ODkxMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJkODg3Y2Q3MC1iYzhlLTQ2MTItODYzNS1lYTYwYjU1ZmU3MzciLCJuYmYiOjE3MjY0Njg5MTAsInN1YiI6IjQ5ZWE3Mjk3LWI0NzgtNDcxNC05NjM2LWQ5ZTk3ZmVkZmNhOSJ9.JLS__gH0wEHwB07DV9Rcrm9mo1xfXpqHoC8pbZ523KHV7QO3n2jrauiB4fVggB5DPe4tTUrp8X1e4nePXPniJyACyC7gmoBX5PJTbUPlalsw0WKOfYOcYXjwJDakId5r Cookie: SESSION=S77dk6NGQyyreWQ1enWRSCSP...wBsNTlidPgTBahs= Dnt: 1 Forwarded: for=172.31.0.1;host=127.0.0.1:9090;proto=http Priority: u=0, i Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: none Sec-Fetch-User: ?1 Upgrade-Insecure-Requests: 1 X-Trp-Catalog: de Try accessing the http://127.0.0.1:9090/admin endpoint with both a user not in the admin group and a user from the admin group. The user not in the admin group should see the \u0026#34;access denied\u0026#34; page, while the user from the admin group should be able to access the endpoint and see the echoed response from our upstream service.\nTo \u0026#34;logout\u0026#34; the user, just delete the cookies for http://127.0.0.1:9090 using the Web-Developer Tools of your browser. Attempts to access any not exposed endpoints, like http://127.0.0.1:9090/foo will always result in the \u0026#34;access denied\u0026#34; page.\nCleanup Just stop the environment with CTRL-C and delete the created files. If you started docker compose in the background, tear the environment down with docker-compose down.\n","description":"This guide will walk you through the process of integrating heimdall with an OpenID Connect provider to implement first-party authentication.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy the end of this guide, you’ll have a functional setup where heimdall uses \u003ca href=\"https://www.keycloak.org/\"\u003eKeycloak\u003c/a\u003e to authenticate users and route requests based on their authentication status and roles for role-based access control.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAlthough this guide uses Keycloak as identity provider (IDP), you can achieve the same results with \u003ca href=\"https://zitadel.com\"\u003eZitadel\u003c/a\u003e, \u003ca href=\"https://github.com/malach-it/boruta-server\"\u003eBoruta\u003c/a\u003e, or any other OpenID Connect-compatible IDP.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_overview\"\u003eOverview\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this guide, we’ll set up a Docker Compose environment where heimdall secures services and controls access to specific endpoints:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/\u003c/code\u003e - This endpoint is open to everyone.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/user\u003c/code\u003e - Accessible only to authenticated users.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/admin\u003c/code\u003e - Accessible only to users with the \u003ccode\u003eadmin\u003c/code\u003e role.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere are also some further endpoints, which you’ll learn about during the setup.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTechnically, the setup includes:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://hub.docker.com/r/containous/whoami/\"\u003econtainous/whoami\u003c/a\u003e - A service that echoes back everything it receives, simulating our main service with endpoints mentioned above.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://www.keycloak.org/\"\u003eKeycloak\u003c/a\u003e - Our identity provider.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://oauth2-proxy.github.io/oauth2-proxy/\"\u003eOAuth2-Proxy\u003c/a\u003e - Handles the Authorization Code Grant flow for the actual user login.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eheimdall - Manages everything to enforce the requirements outlined above.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo be able to follow this guide you need the following tools installed locally:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/install/\"\u003eDocker\u003c/a\u003e,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ca href=\"https://docs.docker.com/compose/install/\"\u003edocker-compose\u003c/a\u003e, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea text editor of your choice.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configure_the_base_setup\"\u003eConfigure the Base Setup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a directory for the configuration files we’ll be using (referred to as the root directory in this guide). Inside this root directory, create two additional directories named \u003ccode\u003erules\u003c/code\u003e and \u003ccode\u003einitdb\u003c/code\u003e. The former will be used for heimdall rules and the latter for DB initialization scripts.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a config file for heimdall named \u003ccode\u003eheimdall-config.yaml\u003c/code\u003e with the following contents in the root directory:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edebug\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emetrics\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eunauthorized\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidentity_info_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://oauth2-proxy:4180/oauth2/userinfo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_data_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ecookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSESSION\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_cookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eSESSION\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003euser\u0026#34;\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etrue\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e==\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003efalse\u0026#34;\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/signer.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclaims\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{- dict \u0026#34;attrs\u0026#34; .Subject.Attributes | toJson -}}\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eerror_handlers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e(9)\u003c/b\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect_to_idp\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://127.0.0.1:9090/oauth2/start?rd={{ .Request.URL | urlenc }}\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect_to_error_page\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://www.google.com/search?q=access+denied\u0026amp;udm=2\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003edefault_rule\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e(10)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003eon_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect_to_error_page\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) in [authorization_error, authentication_error] \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eRequest.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;)\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eproviders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e(11)\u003c/b\u003e\n \u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/rules\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eBy default, heimdall emits logs on \u003ccode\u003eerror\u003c/code\u003e level, but to better understand its operations, we’re setting the log level to \u003ccode\u003edebug\u003c/code\u003e. This way, you’ll see not only the results of rule executions (which is what you would see if we set the log level to \u003ccode\u003einfo\u003c/code\u003e), but also detailed information about what’s happening within each rule. We’re also disabling tracing and metrics collection to avoid errors related to the missing OTEL agent, which is used by default. For more details on logging and other observability options, see the \u003ca href=\"/docs/operations/observability/#_logging\"\u003eObservability\u003c/a\u003e chapter.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWe define our \u003ca href=\"/docs/mechanisms/catalogue/\"\u003ecatalogue of mechanisms\u003c/a\u003e for use in our \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e and \u003ca href=\"/docs/rules/regular_rule/\"\u003eupstream service-specific rules\u003c/a\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines define the \u003ccode\u003eunauthorized\u003c/code\u003e authenticator, named \u003ccode\u003edeny_all\u003c/code\u003e, which rejects all requests.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines define the \u003ccode\u003eanonymous\u003c/code\u003e authenticator, named \u003ccode\u003eanon\u003c/code\u003e, which allows all requests and creates a subject with the ID set to \u003ccode\u003eanonymous\u003c/code\u003e. More information about subjects and other objects can be found \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003ehere\u003c/a\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese and the following lines set up the \u003ccode\u003egeneric\u003c/code\u003e authenticator, named \u003ccode\u003eauth\u003c/code\u003e. This configuration checks if a request includes a \u003ccode\u003eCookie\u003c/code\u003e named \u003ccode\u003eSESSION\u003c/code\u003e, and then sends it to the \u003ccode\u003ehttp://oauth2-proxy:4180/oauth2/userinfo\u003c/code\u003e endpoint to get user information. If successful, heimdall extracts the user identifier from the \u003ccode\u003euser\u003c/code\u003e property in the response. If there’s an error (e.g. the \u003ccode\u003eSESSION\u003c/code\u003e cookie is not present or the response from the OAuth2-Proxy contains an error), an authentication error is triggered.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines define a \u003ccode\u003ecel\u003c/code\u003e authorizer that is configured to always fail. We’ll improve this in our upstream-specific rule.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines define the \u003ccode\u003ejwt\u003c/code\u003e finalizer. It creates a JWT from the subject object with standard claims, setting the \u003ccode\u003esub\u003c/code\u003e claim to the subject’s ID. The key for signing the JWT comes from a key store we’ll configure later.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese two lines define the \u003ccode\u003enoop\u003c/code\u003e finalizer, which we’ll use for public endpoints.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e9\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we set up two \u003ccode\u003eredirect\u003c/code\u003e error handlers: one redirects to the \u003ccode\u003e/oauth2/start\u003c/code\u003e endpoint with a deep link to the current URL, and the other redirects to Google with the search query \u0026#34;access denied\u0026#34;.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e10\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eWith all mechanisms defined, we configure our first rule - the \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e. This rule applies if no other rules match the request and serves as a \u003ca href=\"/docs/concepts/rules/#_default_rule_inheritance\"\u003ebase\u003c/a\u003e for defining regular (upstream service-specific) rules as well. It sets up a default \u003ca href=\"/docs/concepts/pipelines/#_authentication_authorization_pipeline\"\u003eauthentication \u0026amp; authorization pipeline\u003c/a\u003e that rejects all requests using the \u003ccode\u003edeny_all\u003c/code\u003e authenticator. This rejection triggers the \u003ccode\u003eredirect_to_error_page\u003c/code\u003e error handler. If a regular rule overrides this authenticator, a JWT is created using the \u003ccode\u003ejwt\u003c/code\u003e finalizer.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e11\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe last few lines configure the \u003ca href=\"/docs/rules/providers/#_filesystem\"\u003e\u003ccode\u003efile_system\u003c/code\u003e\u003c/a\u003e provider, which loads regular rules from the file system and watches for changes. This allows you to modify the rules while testing.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a file named \u003ccode\u003esigner.pem\u003c/code\u003e and add the following content to it. This file should also be placed in the root directory and will act as our key store, containing the private key referenced in the configuration above.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"s\"\u003e-----BEGIN EC PRIVATE KEY-----\u003c/span\u003e\n\u003cspan class=\"s\"\u003eMIGkAgEBBDALv/dRp6zvm6nmozmB/21viwFCUGBoisHz0v8LSRXGiM5aDywLFmMy\u003c/span\u003e\n\u003cspan class=\"s\"\u003e1jPnw29tz36gBwYFK4EEACKhZANiAAQgZkUS7PCh5tEXXvZk0LDQ4Xn4LSK+vKkI\u003c/span\u003e\n\u003cspan class=\"s\"\u003ezlCZl+oMgud8gacf4uG5ERgju1xdUyfewsXlwepTnWuwhXM7GdnwY5GOxZTwGn3X\u003c/span\u003e\n\u003cspan class=\"s\"\u003eXVwR/5tokqFVrFxt/5c1x7VdccF4nNM=\u003c/span\u003e\n\u003cspan class=\"s\"\u003e-----END EC PRIVATE KEY-----\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nDo not use it for purposes beyond this tutorial!\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNext, we’ll create rules for our main service - the one exposing \u003ccode\u003e/\u003c/code\u003e, \u003ccode\u003e/user\u003c/code\u003e and the \u003ccode\u003e/admin\u003c/code\u003e endpoints. To do this, create a file named \u003ccode\u003eupstream-rules.yaml\u003c/code\u003e in the \u003ccode\u003erules\u003c/code\u003e directory with the following content:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:public\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/favicon.ico\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\n\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:protected\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/user\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/admin\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eupstream:8081\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauth\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRequest.URL.Path == \u0026#39;/admin\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ehas(Subject.Attributes.groups) \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;role:admin\u0026#34; in Subject.Attributes.groups\u003c/span\u003e\n \u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eUser is not admin\u003c/span\u003e\n \u003cspan class=\"na\"\u003eon_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect_to_idp\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) == authentication_error \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eRequest.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;)\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect_to_error_page\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) == authorization_error \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eRequest.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;text/html\u0026#34;)\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis first rule is for the \u003ccode\u003e/\u003c/code\u003e endpoint. It instructs heimdall to pass requests to this endpoint directly through to our upstream service.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe second rule ensures that the \u003ccode\u003e/user\u003c/code\u003e endpoint is only accessible to authenticated users, while the \u003ccode\u003e/admin\u003c/code\u003e endpoint is only accessible to users with the \u003ccode\u003eadmin\u003c/code\u003e role configured in our IDP.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNext, we’ll create a rule for the OAuth2-Proxy, placed behind heimdall and publicly exposing only certain endpoints. Create a new file named \u003ccode\u003eoauth2-proxy-rules.yaml\u003c/code\u003e in the \u003ccode\u003erules\u003c/code\u003e directory with the following content:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2-proxy:public\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/oauth2/start\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/oauth2/callback\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2-proxy:4180\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNext, we’ll create a database initialization script to set up a database for Keycloak. In the \u003ccode\u003einitdb\u003c/code\u003e directory, create a file named \u003ccode\u003einitdb.sh\u003c/code\u003e with the following content, and make it executable by running \u003ccode\u003echmod +x initdb.sh\u003c/code\u003e:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"c\"\u003e#!/bin/bash\u003c/span\u003e\n\u003cspan class=\"nb\"\u003eset\u003c/span\u003e \u003cspan class=\"nt\"\u003e-e\u003c/span\u003e\n\npsql \u003cspan class=\"nt\"\u003e-v\u003c/span\u003e \u003cspan class=\"nv\"\u003eON_ERROR_STOP\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e1 \u003cspan class=\"nt\"\u003e--username\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e$POSTGRES_USER\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;\u0026lt;-\u003c/span\u003e\u003cspan class=\"no\"\u003eEOSQL\u003c/span\u003e\u003cspan class=\"sh\"\u003e\n CREATE USER keycloak WITH PASSWORD \u0026#39;keycloak\u0026#39;;\n CREATE DATABASE keycloak OWNER keycloak;\n\u003c/span\u003e\u003cspan class=\"no\"\u003eEOSQL\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNow, let’s bring everything together using a Docker Compose file. Create a file named \u003ccode\u003edocker-compose.yaml\u003c/code\u003e in the root directory with the following content:\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eservices\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheimdall\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e(1)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edadrus/heimdall:dev\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e9090:4455\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eserve proxy --c /etc/heimdall/config.yaml --insecure\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./heimdall-config.yaml:/etc/heimdall/config.yaml:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./rules:/etc/heimdall/rules:ro\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./signer.pem:/etc/heimdall/signer.pem:ro\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eupstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e(2)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003econtainous/whoami:latest\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e--port=8081\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eoauth2-proxy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e(3)\u003c/b\u003e\n \u003cspan class=\"na\"\u003edepends_on\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak\u003c/span\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003equay.io/oauth2-proxy/oauth2-proxy:v7.6.0-amd64\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e--http-address\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e0.0.0.0:4180\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenvironment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_CLIENT_ID\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eplaceholder\u003c/span\u003e \u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e(4)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_CLIENT_SECRET\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eplaceholder\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_REDIRECT_URL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://127.0.0.1:9090/oauth2/callback\u003c/span\u003e \u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e(5)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_PROVIDER\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak-oidc\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_SKIP_PROVIDER_BUTTON\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_COOKIE_SECRET\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecure!!!!!!\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_COOKIE_NAME\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSESSION\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_WHITELIST_DOMAINS\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1:9090\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_OIDC_ISSUER_URL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://keycloak:8080/realms/test\u003c/span\u003e \u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e(6)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e \u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e(7)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_EMAIL_DOMAINS\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e*\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_OIDC_EXTRA_AUDIENCES\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccount\u003c/span\u003e \u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e(8)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_LOGIN_URL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://127.0.0.1:8080/realms/test/protocol/openid-connect/auth\u003c/span\u003e \u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e(9)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_OIDC_JWKS_URL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://keycloak:8080/realms/test/protocol/openid-connect/certs\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_REDEEM_URL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp://keycloak:8080/realms/test/protocol/openid-connect/token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_INSECURE_OIDC_SKIP_ISSUER_VERIFICATION\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003eOAUTH2_PROXY_SKIP_OIDC_DISCOVERY\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003ekeycloak\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e(10)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003equay.io/keycloak/keycloak:25.0.4\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecommand\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003estart-dev\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e--http-port\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e8080\u0026#34;\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003eports\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e8080:8080\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenvironment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_HOSTNAME\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_HOSTNAME_PORT\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e8080\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_HOSTNAME_STRICT_BACKCHANNEL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etrue\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKEYCLOAK_ADMIN\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eadmin\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKEYCLOAK_ADMIN_PASSWORD\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eadmin\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_HEALTH_ENABLED\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003etrue\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_LOG_LEVEL\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003einfo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_DB_URL_HOST\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003epostgresql\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_DB\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003epostgres\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_DB_USERNAME\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak\u003c/span\u003e\n \u003cspan class=\"na\"\u003eKC_DB_PASSWORD\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak\u003c/span\u003e\n \u003cspan class=\"na\"\u003edepends_on\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003epostgresql\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003epostgresql\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e(11)\u003c/b\u003e\n \u003cspan class=\"na\"\u003eimage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003epostgres:13.11\u003c/span\u003e\n \u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003evolume\u003c/span\u003e\n \u003cspan class=\"na\"\u003esource\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003epostgres-db\u003c/span\u003e\n \u003cspan class=\"na\"\u003etarget\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/var/lib/postgresql/data\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread_only\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e./initdb:/docker-entrypoint-initdb.d\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenvironment\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePOSTGRES_USER=postgres\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePOSTGRES_PASSWORD=postgres\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003evolumes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epostgres-db\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"colist arabic\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"1\"\u003e\u003c/i\u003e\u003cb\u003e1\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eHere, we configure heimdall to use the previously defined configuration.\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWe’re using the \u003ccode\u003e--insecure\u003c/code\u003e flag here to simplify our setup, which disables enforcement of some security settings you can learn about more \u003ca href=\"/docs/operations/security/#_defaults\"\u003ehere\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"2\"\u003e\u003c/i\u003e\u003cb\u003e2\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis section sets up the main service that we’ll be protecting.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"3\"\u003e\u003c/i\u003e\u003cb\u003e3\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis section defines the OAuth2-Proxy configuration, which heimdall will use to handle the Authorization Code Grant flow and manage the authentication session with a \u003ccode\u003eSESSION\u003c/code\u003e cookie.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"4\"\u003e\u003c/i\u003e\u003cb\u003e4\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe client ID and client secret values are placeholders. We will configure these in Keycloak.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"5\"\u003e\u003c/i\u003e\u003cb\u003e5\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eSince the redirect URI, exposed as \u003ccode\u003e/oauth2/callback\u003c/code\u003e, is behind heimdall, we use the publicly accessible endpoint here.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"6\"\u003e\u003c/i\u003e\u003cb\u003e6\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe URL of the issuer that OAuth2-Proxy will use. We’ll create a corresponding realm in Keycloak to match this configuration.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"7\"\u003e\u003c/i\u003e\u003cb\u003e7\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThe following two lines are required as we don’t want keycloak to verify the email addresses of the users we’ll be creating, and we want to allow any email domain.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"8\"\u003e\u003c/i\u003e\u003cb\u003e8\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eTo avoid creating a mapper to let Keycloak set a proper \u003ccode\u003eaud\u003c/code\u003e claim value, we allow the usage of \u003ccode\u003eaccount\u003c/code\u003e audience set by Keycloak by default.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"9\"\u003e\u003c/i\u003e\u003cb\u003e9\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThese lines are only required as Keycloak is part of our docker compose setup, and we have to use different domain names while communicating with it.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"10\"\u003e\u003c/i\u003e\u003cb\u003e10\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eThis section sets up Keycloak.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ci class=\"conum\" data-value=\"11\"\u003e\u003c/i\u003e\u003cb\u003e11\u003c/b\u003e\u003c/td\u003e\n\u003ctd\u003eFinally, this section configures our database.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_create_a_realm_and_a_client_in_keycloak\"\u003eCreate a Realm and a Client in Keycloak\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith the above configuration in place, follow these steps to start Keycloak and the database, initialize both, and create the OAuth2-Proxy client:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eIn the root directory, run \u003ccode\u003edocker compose up postgresql keycloak\u003c/code\u003e. Wait until the database is initialized and Keycloak has started.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOpen your browser and go to \u003ccode\u003ehttp://127.0.0.1:8080\u003c/code\u003e. Log in using the admin credentials (both the username and password are set to \u003ccode\u003eadmin\u003c/code\u003e in our setup).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate a Realm named \u003ccode\u003etest\u003c/code\u003e. For detailed instructions, refer to the Keycloak documentation on \u003ca href=\"https://www.keycloak.org/docs/latest/server_admin/index.html#proc-creating-a-realm_server_administration_guide\"\u003e creating a realm\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWithin the \u003ccode\u003etest\u003c/code\u003e realm, create an OpenID Client. Follow the Keycloak documentation on \u003ca href=\"https://www.keycloak.org/docs/latest/server_admin/index.html#proc-creating-oidc-client_server_administration_guide\"\u003ecreating an OIDC client\u003c/a\u003e. Enable \u0026#34;Client authentication\u0026#34; and \u0026#34;Standard Flow\u0026#34;, set \u003ccode\u003ehttp://127.0.0.1:9090/oauth2/callback\u003c/code\u003e as the \u0026#34;Valid Redirect URI\u0026#34; and \u003ccode\u003ehttp://127.0.0.1:9090/\u003c/code\u003e as the \u0026#34;Home URL\u0026#34; and \u0026#34;Valid post logout redirect URIs\u0026#34; and note the \u0026#34;Client ID\u0026#34; and \u0026#34;Client Secret\u0026#34; (later can be found under the \u0026#34;Credentials\u0026#34; tab after completing the client creation wizard); we will use these to complete the OAuth2-Proxy configuration in our Docker Compose file.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eStop the docker compose setup with \u003ccode\u003eCTRL-C\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_update_oauth2_proxy_configuration\"\u003eUpdate OAuth2-Proxy Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWe can now finalize the configuration and use the proper client id and secret for OAuth2-Proxy\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eUpdate the \u003ccode\u003eOAUTH2_PROXY_CLIENT_ID\u003c/code\u003e and \u003ccode\u003eOAUTH2_PROXY_CLIENT_SECRET\u003c/code\u003e in the configuration of the OAuth2-Proxy in the docker compose file with the \u0026#34;Client ID\u0026#34; and \u0026#34;Client Secret\u0026#34; values from Keycloak\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_use_the_setup\"\u003eUse the Setup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWe now have almost everything set up. The final step is to create a few users, including at least one with the \u003ccode\u003eadmin\u003c/code\u003e role assigned.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eIn the root directory, run \u003ccode\u003edocker compose up\u003c/code\u003e. Wait until all services are up and running.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOpen your browser and navigate to \u003ccode\u003ehttp://127.0.0.1:8080\u003c/code\u003e. Log in using the admin credentials (both username and password are set to \u003ccode\u003eadmin\u003c/code\u003e).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eSelect the \u003ccode\u003etest\u003c/code\u003e realm and create an \u003ccode\u003eadmin\u003c/code\u003e group with a role named \u003ccode\u003eadmin\u003c/code\u003e assigned to it. For guidance, refer to the Keycloak documentation on creating \u003ca href=\"https://www.keycloak.org/docs/latest/server_admin/index.html#proc-managing-groups_server_administration_guide\"\u003eGroups\u003c/a\u003e and \u003ca href=\"https://www.keycloak.org/docs/latest/server_admin/index.html#proc-creating-realm-roles_server_administration_guide\"\u003eRoles\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCreate several users following the Keycloak documentation on \u003ca href=\"https://www.keycloak.org/docs/latest/server_admin/index.html#proc-creating-user_server_administration_guide\"\u003emanaging users\u003c/a\u003e, and assign some of them to the \u003ccode\u003eadmin\u003c/code\u003e group. Disable email verification during user creation to avoid sending verification emails to potentially non-existent addresses.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNow, let’s test the setup:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eNavigate to \u003ccode\u003ehttp://127.0.0.1:9090/\u003c/code\u003e. You should see some text similar to the one shown below. This text is the response from our upstream service, which echoes back everything the browser sends in its request.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003eHostname: 39f1815dd8ac\nIP: 127.0.0.1\nIP: ::1\nIP: 172.31.0.3\nRemoteAddr: 172.31.0.2:37908\nGET / HTTP/1.1\nHost: upstream:8081\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8\nAccept-Encoding: gzip, deflate, br, zstd\nAccept-Language: de,en-US;q=0.7,en;q=0.3\nDnt: 1\nForwarded: for=172.31.0.1;host=127.0.0.1:9090;proto=http\nPriority: u=0, i\nSec-Fetch-Dest: document\nSec-Fetch-Mode: navigate\nSec-Fetch-Site: none\nSec-Fetch-User: ?1\nUpgrade-Insecure-Requests: 1\nX-Trp-Catalog: de\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAttempt to access the \u003ccode\u003ehttp://127.0.0.1:9090/user\u003c/code\u003e endpoint. You should be redirected to the Keycloak login page. Log in with any of the users you configured. After logging in, you should be redirected back to \u003ccode\u003ehttp://127.0.0.1:9090/user\u003c/code\u003e, where you’ll see some text similar to the one shown below. This indicates that the request hit the \u003ccode\u003e/user\u003c/code\u003e endpoint of our upstream service. You should also see a JWT token in the \u003ccode\u003eAuthorization\u003c/code\u003e header, which is the result of the JWT finalizer we configured.\u003c/p\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003eHostname: 39f1815dd8ac\nIP: 127.0.0.1\nIP: ::1\nIP: 172.31.0.3\nRemoteAddr: 172.31.0.2:37908\nGET /user HTTP/1.1\nHost: upstream:8081\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8\nAccept-Encoding: gzip, deflate, br, zstd\nAccept-Language: de,en-US;q=0.7,en;q=0.3\nAuthorization: Bearer eyJhbGciOiJFUzM4NCIsImtpZCI6ImIzNDA3N2ZlNWI5NDczYzBjMmY3NDNmYWQ0MmY3ZDU0YWM3ZTFkN2EiLCJ0eXAiOiJKV1QifQ.eyJhdHRycyI6eyJlbWFpbCI6InRlc3QxQGV4YW1wbGUuY29tIiwiZ3JvdXBzIjpbInJvbGU6ZGVmYXVsdC1yb2xlcy10ZXN0Iiwicm9sZTpvZmZsaW5lX2FjY2VzcyIsInJvbGU6YWRtaW4iLCJyb2xlOnVtYV9hdXRob3JpemF0aW9uIiwicm9sZTphY2NvdW50Om1hbmFnZS1hY2NvdW50Iiwicm9sZTphY2NvdW50Om1hbmFnZS1hY2NvdW50LWxpbmtzIiwicm9sZTphY2NvdW50OnZpZXctcHJvZmlsZSJdLCJwcmVmZXJyZWRVc2VybmFtZSI6InRlc3QxIiwidXNlciI6IjQ5ZWE3Mjk3LWI0NzgtNDcxNC05NjM2LWQ5ZTk3ZmVkZmNhOSJ9LCJleHAiOjE3MjY0NjkyMTAsImlhdCI6MTcyNjQ2ODkxMCwiaXNzIjoiaGVpbWRhbGwiLCJqdGkiOiJkODg3Y2Q3MC1iYzhlLTQ2MTItODYzNS1lYTYwYjU1ZmU3MzciLCJuYmYiOjE3MjY0Njg5MTAsInN1YiI6IjQ5ZWE3Mjk3LWI0NzgtNDcxNC05NjM2LWQ5ZTk3ZmVkZmNhOSJ9.JLS__gH0wEHwB07DV9Rcrm9mo1xfXpqHoC8pbZ523KHV7QO3n2jrauiB4fVggB5DPe4tTUrp8X1e4nePXPniJyACyC7gmoBX5PJTbUPlalsw0WKOfYOcYXjwJDakId5r\nCookie: SESSION=S77dk6NGQyyreWQ1enWRSCSP...wBsNTlidPgTBahs=\nDnt: 1\nForwarded: for=172.31.0.1;host=127.0.0.1:9090;proto=http\nPriority: u=0, i\nSec-Fetch-Dest: document\nSec-Fetch-Mode: navigate\nSec-Fetch-Site: none\nSec-Fetch-User: ?1\nUpgrade-Insecure-Requests: 1\nX-Trp-Catalog: de\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eTry accessing the \u003ccode\u003ehttp://127.0.0.1:9090/admin\u003c/code\u003e endpoint with both a user not in the \u003ccode\u003eadmin\u003c/code\u003e group and a user from the \u003ccode\u003eadmin\u003c/code\u003e group. The user not in the \u003ccode\u003eadmin\u003c/code\u003e group should see the \u0026#34;access denied\u0026#34; page, while the user from the \u003ccode\u003eadmin\u003c/code\u003e group should be able to access the endpoint and see the echoed response from our upstream service.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nTo \u0026#34;logout\u0026#34; the user, just delete the cookies for \u003ccode\u003ehttp://127.0.0.1:9090\u003c/code\u003e using the Web-Developer Tools of your browser.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAttempts to access any not exposed endpoints, like \u003ccode\u003ehttp://127.0.0.1:9090/foo\u003c/code\u003e will always result in the \u0026#34;access denied\u0026#34; page.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cleanup\"\u003eCleanup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eJust stop the environment with \u003ccode\u003eCTRL-C\u003c/code\u003e and delete the created files. If you started docker compose in the background, tear the environment down with \u003ccode\u003edocker-compose down\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Guides","Authentication Protocols \u0026 Services"],"tags":null,"title":"First-Party Authentication with OpenID Connect","url":"/guides/authn/oidc_first_party_auth/"},{"categories":null,"content":" Configuration in heimdall can refer to two different things:\nthe static startup configuration, which is the scope of this document and\nthe configuration of rules, respectively rule sets, which you can find here.\nElements in the static configuration set up the services, like the main service, which basically defines the main entry point, heimdall will listen to for the actual access control decision purposes, the observability capabilities, like logging, the mechanism catalogue, the default rule, as well as the rule providers (these elements are not expected to change often).\nThe rule set contains everything that defines how the requests are handled by heimdall for your system. This configuration can change and is seamlessly hot-reloaded, without any request interruption or connection loss.\nOverview There are two different, not mutually exclusive (you can combine them), ways to define static configuration options in Heimdall:\nin a configuration file (only YAML is supported as format)\nas environment variables\nThe evaluation happens also in the order stated above. That also means, you can always overwrite configuration options defined in a configuration file with corresponding environment variables.\nIf no configuration is provided, heimdall will set useful defaults. These are however not enough, as heimdall doesn’t know your context - which mechanisms are required for the one or the other of your upstream services. So, you’ll not really be able to use heimdall as all requests will be answered with an HTTP 405 Method Not Allowed response code.\nConfiguration File At start up, heimdall searches for static configuration in a file named heimdall.yaml in\n/etc/heimdall\n$HOME/.config\nthe current working directory\nYou can also override this using the config argument: heimdall --config \u0026lt;path-to-your-config-file\u0026gt;.\nThe values in the configuration file can also make use of environment variables. Access to these happens using Bash syntax. Following expressions are supported:\n${var} - Value of $var\n${var=default} - If $var is not set, evaluate expression as default\n${var:=default} - If $var is not set or is empty, evaluate expression as default\nExample 1. Possible minimal fully working configuration The configuration below defines a default rule which lets heimdall create a JSON Web Token (JWT) with sub claim set to anonymous for every request on every URL for the HTTP methods GET and POST. The JWT itself will be put into the Authorization header as a bearer token.\nlog: level: info mechanisms: authenticators: - id: anonymous_authenticator type: anonymous finalizers: - id: create_jwt type: jwt config: signer: key_store: path: /etc/heimdall/signer.pem default_rule: execute: - authenticator: anonymous_authenticator - finalizer: create_jwt Example 2. Configuration with a mechanism defined using environment variables substitution mechanisms: authenticators: - id: hydra_authenticator type: oauth2_introspection config: introspection_endpoint: url: https://hydra:4445/oauth2/introspect auth: type: basic_auth config: user: ${INTROSPECT_EP_USER} password: ${INTROSPECT_EP_PASSWORD} finalizers: - id: create_jwt type: jwt config: signer: key_store: path: ${SIGNER_KEY_STORE_FILE} Environment Variables Every configuration property, which can be defined in a configuration file can also be defined as environment variable. Following rules apply:\nIf not specified while starting heimdall, all variables start with HEIMDALLCFG_ prefix.\nIf for whatever reason, your environment configuration contains variables starting with HEIMDALLCFG_, which do not define heimdall specific configuration, heimdall will refuse starting if such configuration variable clashes (has an unexpected type) with heimdall’s configuration properties (even for environment variables, the configuration is type safe). You can overcome such situation, by ether renaming such variables, or, if this is not possible, make use of the --env-config-prefix flag with heimdall’s serve command. Properties in a hierarchy are separated by _\nE.g. the log level can be set to info in a config file as also shown in the above example with\nlog: level: info and using an environment variable with\nHEIMDALLCFG_LOG_LEVEL=info Array entries must be defined using _\u0026lt;IDX\u0026gt;[_], with IDX being the index of the array starting with 0 and _ in brackets being only required, if the value of the configured element has a structure/hierarchy.\nE.g. the trusted_proxies property of the main service can be configured in a config file as\nserve: trusted_proxies: - 192.168.1.0/24 - 192.168.2.0/24 and using environment variables with\nHEIMDALLCFG_SERVE_TRUSTED__PROXIES_0=192.168.1.0/24 HEIMDALLCFG_SERVE_TRUSTED__PROXIES_0=192.168.2.0/24 For structured configuration, like the definition of the authenticators in the example above\nmechanisms: authenticators: - id: anonymous_authenticator type: anonymous The corresponding environment variables would be\nHEIMDALLCFG_MECHANISMS_AUTHENTICATORS_0_ID=anonymous_authenticator HEIMDALLCFG_MECHANISMS_AUTHENTICATORS_0_TYPE=anonymous If a name of a property has _ it must be escaped with an additional _.\nE.g. by setting the span processor to simple, you can instruct heimdall to synchronously export the created spans via configured exporters.\ntracing: span_processor: simple and using the environment variables with\nHEIMDALLCFG_TRACING_SPAN__PROCESSOR=simple ","description":"This page explains the available configuration options in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration in heimdall can refer to two different things:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ethe static startup configuration, which is the scope of this document and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe configuration of rules, respectively rule sets, which you can find \u003ca href=\"/docs/rules/rule_sets/\"\u003ehere\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eElements in the static configuration set up the services, like the \u003ca href=\"/docs/services/main/\"\u003emain service\u003c/a\u003e, which basically defines the main entry point, heimdall will listen to for the actual access control decision purposes, the observability capabilities, like \u003ca href=\"/docs/operations/observability/#_logging\"\u003elogging\u003c/a\u003e, the \u003ca href=\"/docs/concepts/mechanisms/\"\u003emechanism catalogue\u003c/a\u003e, the \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e, as well as the \u003ca href=\"/docs/rules/providers/\"\u003erule providers\u003c/a\u003e (these elements are not expected to change often).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe rule set contains everything that defines how the requests are handled by heimdall for your system.\nThis configuration can change and is seamlessly hot-reloaded, without any request interruption or connection loss.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_overview\"\u003eOverview\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere are two different, not mutually exclusive (you can combine them), ways to define static configuration options in Heimdall:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003ein a \u003ca href=\"#_configuration_file\"\u003econfiguration file\u003c/a\u003e (only \u003ca href=\"https://yaml.org/spec/1.2.2/\"\u003eYAML\u003c/a\u003e is supported as format)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eas \u003ca href=\"#_environment_variables\"\u003eenvironment variables\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe evaluation happens also in the order stated above.\nThat also means, you can always overwrite configuration options defined in a configuration file with corresponding environment variables.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf no configuration is provided, heimdall will set useful defaults.\nThese are however not enough, as heimdall doesn’t know your context - which mechanisms are required for the one or the other of your upstream services.\nSo, you’ll not really be able to use heimdall as all requests will be answered with an HTTP \u003ccode\u003e405 Method Not Allowed\u003c/code\u003e response code.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration_file\"\u003eConfiguration File\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAt start up, heimdall searches for static configuration in a file named \u003ccode\u003eheimdall.yaml\u003c/code\u003e in\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/etc/heimdall\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e$HOME/.config\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe current working directory\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can also override this using the \u003ccode\u003econfig\u003c/code\u003e argument: \u003ccode\u003eheimdall --config \u0026lt;path-to-your-config-file\u0026gt;\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe values in the configuration file can also make use of environment variables. Access to these happens using Bash syntax. Following expressions are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e${var}\u003c/code\u003e - Value of \u003ccode\u003e$var\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e${var=default}\u003c/code\u003e - If \u003ccode\u003e$var\u003c/code\u003e is not set, evaluate expression as \u003ccode\u003edefault\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e${var:=default}\u003c/code\u003e - If \u003ccode\u003e$var\u003c/code\u003e is not set or is empty, evaluate expression as \u003ccode\u003edefault\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Possible minimal fully working configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration below defines a \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e which lets heimdall create a JSON Web Token (JWT) with \u003ccode\u003esub\u003c/code\u003e claim set to \u003ccode\u003eanonymous\u003c/code\u003e for every request on every URL for the HTTP methods GET and POST.\nThe JWT itself will be put into the \u003ccode\u003eAuthorization\u003c/code\u003e header as a bearer token.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003einfo\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/signer.pem\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003edefault_rule\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous_authenticator\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Configuration with a mechanism defined using environment variables substitution\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehydra_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_introspection\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eintrospection_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://hydra:4445/oauth2/introspect\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${INTROSPECT_EP_USER}\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${INTROSPECT_EP_PASSWORD}\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${SIGNER_KEY_STORE_FILE}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_environment_variables\"\u003eEnvironment Variables\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEvery configuration property, which can be defined in a \u003ca href=\"#_configuration_file\"\u003econfiguration file\u003c/a\u003e can also be defined as environment variable.\nFollowing rules apply:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIf not specified while starting heimdall, all variables start with \u003ccode\u003eHEIMDALLCFG_\u003c/code\u003e prefix.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf for whatever reason, your environment configuration contains variables starting with \u003ccode\u003eHEIMDALLCFG_\u003c/code\u003e, which do not define heimdall specific configuration, heimdall will refuse starting if such configuration variable clashes (has an unexpected type) with heimdall’s configuration properties (even for environment variables, the configuration is type safe).\nYou can overcome such situation, by ether renaming such variables, or, if this is not possible, make use of the \u003ccode\u003e--env-config-prefix\u003c/code\u003e flag with heimdall’s \u003ccode\u003eserve\u003c/code\u003e command.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eProperties in a hierarchy are separated by \u003ccode\u003e_\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g. the log level can be set to \u003ccode\u003einfo\u003c/code\u003e in a config file as also shown in the above example with\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003einfo\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eand using an environment variable with\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eHEIMDALLCFG_LOG_LEVEL\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003einfo\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eArray entries must be defined using \u003ccode\u003e_\u0026lt;IDX\u0026gt;[_]\u003c/code\u003e, with \u003ccode\u003eIDX\u003c/code\u003e being the index of the array starting with \u003ccode\u003e0\u003c/code\u003e and \u003ccode\u003e_\u003c/code\u003e in brackets being only required, if the value of the configured element has a structure/hierarchy.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g. the \u003ccode\u003etrusted_proxies\u003c/code\u003e property of the \u003ca href=\"/docs/services/main/\"\u003emain service\u003c/a\u003e can be configured in a config file as\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eserve\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etrusted_proxies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e192.168.1.0/24\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e192.168.2.0/24\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eand using environment variables with\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eHEIMDALLCFG_SERVE_TRUSTED__PROXIES_0\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e192.168.1.0/24\n\u003cspan class=\"nv\"\u003eHEIMDALLCFG_SERVE_TRUSTED__PROXIES_0\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e192.168.2.0/24\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor structured configuration, like the definition of the authenticators in the example above\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe corresponding environment variables would be\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eHEIMDALLCFG_MECHANISMS_AUTHENTICATORS_0_ID\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003eanonymous_authenticator\n\u003cspan class=\"nv\"\u003eHEIMDALLCFG_MECHANISMS_AUTHENTICATORS_0_TYPE\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003eanonymous\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf a name of a property has \u003ccode\u003e_\u003c/code\u003e it must be escaped with an additional \u003ccode\u003e_\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g. by setting the span processor to \u003ccode\u003esimple\u003c/code\u003e, you can instruct heimdall to synchronously export the created spans via configured exporters.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003espan_processor\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esimple\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eand using the environment variables with\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eHEIMDALLCFG_TRACING_SPAN__PROCESSOR\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003esimple\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Operations"],"tags":null,"title":"Configuration ","url":"/docs/operations/configuration/"},{"categories":null,"content":" Usage Patterns heimdall [command] [flags] [arguments] Use heimdall help to get overview about available commands, respectively heimdall [command] help for help on any command.\nFlag’s usage:\n# set flag_argument to flag(s) heimdall [--flag=flag_argument] [-f [flag_argument]] E.g.\nheimdall validate config -c config.yaml Commands completion\nGenerates the autocompletion script for the specified shell.\nhealth\nCalls heimdall’s healthcheck endpoint to verify the status of the deployment.\nhelp\nProvides an overview about the available commands and their descriptions.\nserve\nStarts heimdall in the decision, or the reverse proxy operation mode.\nvalidate\nValidates heimdall configuration, like rules or the actual configuration.\n","description":"Here, you can find the description of heimdall's command line interface.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_usage_patterns\"\u003eUsage Patterns\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eheimdall \u003cspan class=\"o\"\u003e[\u003c/span\u003e\u003cspan class=\"nb\"\u003ecommand\u003c/span\u003e\u003cspan class=\"o\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e[\u003c/span\u003eflags] \u003cspan class=\"o\"\u003e[\u003c/span\u003earguments]\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUse \u003ccode\u003eheimdall help\u003c/code\u003e to get overview about available commands, respectively \u003ccode\u003eheimdall [command] help\u003c/code\u003e for help on any command.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFlag’s usage:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"c\"\u003e# set flag_argument to flag(s)\u003c/span\u003e\nheimdall \u003cspan class=\"o\"\u003e[\u003c/span\u003e\u003cspan class=\"nt\"\u003e--flag\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003eflag_argument] \u003cspan class=\"o\"\u003e[\u003c/span\u003e\u003cspan class=\"nt\"\u003e-f\u003c/span\u003e \u003cspan class=\"o\"\u003e[\u003c/span\u003eflag_argument]]\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eheimdall validate config \u003cspan class=\"nt\"\u003e-c\u003c/span\u003e config.yaml\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_commands\"\u003eCommands\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ecompletion\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eGenerates the autocompletion script for the specified shell.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ehealth\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCalls heimdall’s healthcheck endpoint to verify the status of the deployment.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ehelp\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eProvides an overview about the available commands and their descriptions.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eserve\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eStarts heimdall in the decision, or the reverse proxy operation mode.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003evalidate\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eValidates heimdall configuration, like rules or the actual configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Operations"],"tags":null,"title":"CLI","url":"/docs/operations/cli/"},{"categories":null,"content":" Logging Heimdall’s implementation uses zerolog - Zero Allocation JSON Logger, which can however also log in plain text. All emitted log statements include information related to distributed tracing (if tracing is enabled) so that not only log statements can be correlated to traces, but also all log statements belonging to single request/transaction can be correlated as well.\nConfiguration Logging configuration can be adjusted in the log property of heimdall’s configuration and supports following properties.\nformat: string (optional)\nWith text and gelf being the available formats. text is the default format. And gelf defines a JSON format adhering to GELF.\nUsage of text (default) format is not recommended for production deployments as it requires more computational resources and is hence slow. Example 1. Configuring logging to emit logs using GELD format. log: format: gelf level: string (optional)\nFollowing log levels are available: trace, debug, info, warn, error, fatal, panic and disabled. The last one effectively disables logging. You usually do not want to do this. By default, the level is set to error.\ndebug and trace log levels are not meant for production as setting log level to one of these will result in a high log verbosity and also affect performance pretty much. Both are only meant for setup analysis and debugging! trace log level will also dump all incoming and outgoing HTTP requests and responses, as well as the contents of objects used in templates. That dump is unedited. That means sensitive data will be available in logs. Due to some limitations of the GRPC framework capabilities, setting log level to trace will not dump GRPC requests and responses. If you need these for analysis purposes (e.g. when debugging the integration with envoy proxy), you’ll have to set GODEBUG as well as the GRPC_GO_LOG_VERBOSITY_LEVEL and GRPC_GO_LOG_SEVERITY_LEVEL environment variables. Example 2. Configuring logging to emit logs in debug level. log: level: debug Regular Log Events If you configure heimdall to log in text format, you can expect output similar to the one shown below:\n2022-08-03T12:51:48+02:00 INF Opentelemetry tracing initialized. 2022-08-03T12:51:48+02:00 INF Instantiating in memory cache 2022-08-03T12:51:48+02:00 DBG Creating rule set event queue. 2022-08-03T12:51:48+02:00 INF Loading pipeline definitions 2022-08-03T12:51:48+02:00 DBG Loading definitions for authenticators 2022-08-03T12:51:48+02:00 DBG Loading pipeline definition id=anonymous_authenticator type=anonymous ... 2022-08-03T12:51:52+02:00 DBG Decision endpoint called 2022-08-03T12:51:52+02:00 DBG Executing default rule 2022-08-03T12:51:52+02:00 DBG Authenticating using anonymous authenticator 2022-08-03T12:51:52+02:00 DBG Finalizing using JWT finalizer 2022-08-03T12:51:52+02:00 DBG Generating new JWT 2022-08-03T12:51:52+02:00 DBG Finalizing request Usage of this format is not recommended for production deployments as it requires more computational resources and is hence slow. Otherwise, if you configure it to use gelf (see GELF for format details) format, the output will look as follows:\n{\u0026#34;_level_name\u0026#34;: \u0026#34;INFO\u0026#34;, \u0026#34;version\u0026#34;:\u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 6, \u0026#34;short_message\u0026#34;: \u0026#34;Opentracing tracer initialized.\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;INFO\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 6, \u0026#34;short_message\u0026#34;: \u0026#34;Instantiating in memory cache\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 7, \u0026#34;short_message\u0026#34;: \u0026#34;Creating rule set event queue.\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;INFO\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 6, \u0026#34;short_message\u0026#34;: \u0026#34;Loading pipeline definitions\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 7,\u0026#34;short_message\u0026#34;: \u0026#34;Loading definitions for authenticators\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;id\u0026#34;: \u0026#34;anonymous_authenticator\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;anonymous\u0026#34;,\u0026#34;timestamp\u0026#34;: 1659523288, \u0026#34;level\u0026#34;: 7, \u0026#34;short_message\u0026#34;: \u0026#34;Loading pipeline definition\u0026#34;} ... {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Decision endpoint called\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;:1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Executing default rule\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;:\u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;:1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Authenticating using anonymous authenticator\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Finalizing using JWT finalizer\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Generating new JWT\u0026#34;} {\u0026#34;_level_name\u0026#34;: \u0026#34;DEBUG\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523295, \u0026#34;level\u0026#34;: 7, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;Finalizing request\u0026#34;} Each log statement does also include the following fields in both log formats for incoming requests if tracing is enabled:\n_trace_id - The trace id as defined by OpenTelemetry.\n_span_id - The span id as defined by OpenTelemetry of the current transaction.\n_parent_id - The span id of the callee, which started the given transaction. Only present if the callee set the corresponding tracing header.\nAccess Log Events In addition to regular logs, heimdall emits access logs. These events are always emitted regardless the configured log level and the log level of these events in the log output is always INFO.\nEach request to any of heimdall’s endpoints will result in two access events:\nevent describing the start of the transaction, and an\nevent describing the finalization of the transaction.\nFollowing are the fields, which are always set for both events:\n_tx_start - Timestamp in Unix epoch format, when the transaction started.\n_client_ip - The IP of the client of the request.\nIf the event has been emitted for an HTTP request, following fields are set as well:\n_http_method - The HTTP method used by the client while calling heimdall’s endpoint.\n_http_path - The used HTTP path.\n_http_user_agent - The agent used by the client. The value is taken from the HTTP \u0026#34;User-Agent\u0026#34; header.\n_http_host - The host part of the URI, the client is using while communicating with Heimdall.\n_http_scheme - The scheme part of the URI, the client is using while communicating with Heimdall.\nIf the event has been emitted for a GRPC request, following fields are set:\n_grpc_method - The full GRPC method used.\nIf the request comes from an intermediary, like e.g. an API Gateway and heimdall is configured to trust that \u0026#34;proxy\u0026#34; (see trusted_proxies configuration), then following fields will be part of the events as well if the corresponding HTTP headers were sent.\n_http_x_forwarded_proto - The value of the \u0026#34;X-Forwarded-Proto\u0026#34; header.\n_http_x_forwarded_host - The value of the \u0026#34;X-Forwarded-Host\u0026#34; header.\n_http_x_forwarded_uri - The value of the \u0026#34;X-Forwarded-Uri\u0026#34; header.\n_http_x_forwarded_for - The value of the \u0026#34;X-Forwarded-For\u0026#34; header.\n_http_forwarded - The value of the \u0026#34;Forwarded\u0026#34; header.\nFollowing are the fields, which are set in the transaction finalization event in addition:\n_body_bytes_sent - The length of the response body.\n_tx_duration_ms - The duration of the transaction in milliseconds. If heimdall is operated in proxy mode, it will also include the time used to communicate with the upstream service.\n_access_granted - Set either to true or false, indicating whether heimdall granted access or not.\n_subject - The subject identifier if the access was granted.\n_error - The information about an error, which e.g. led to the denial of the request.\nIf the finalization event has been emitted for an HTTP request, following fields are set as well:\n_http_status_code - The numeric HTTP response status code\nIf the finalization event has been emitted for a GRPC request, following fields are set:\n_grpc_status_code - The numeric GRPC status code.\nFollowing are the fields, which are set if tracing is enabled:\n_trace_id - The trace id as defined by OpenTelemetry.\n_span_id - The span id as defined by OpenTelemetry of the current transaction.\n_parent_id - The span id of the callee, which started the given transaction. Only present if the callee set the corresponding tracing header.\nIf you configure heimdall to log in text format, you can expect output as shown below:\n2022-08-03T12:40:16+02:00 INF TX started _client_ip=127.0.0.1 _http_host=127.0.0.1:4468 _http_method=GET _http_path=/foo _http_scheme=http _http_user_agent=curl/7.74.0 _parent_id=3449bda63ed70206 _span_id=f57c007257fee0ed _trace_id=00000000000000000a5af97bffe6a8a2 _tx_start=1659523216 .... 2022-08-03T12:40:16+02:00 INF TX finished _access_granted=true _body_bytes_sent=0 _client_ip=127.0.0.1 _http_host=127.0.0.1:4468 _http_method=GET _http_path=/foo _http_scheme=http _http_status_code=202 _http_user_agent=curl/7.74.0 _subject=anonymous _parent_id=3449bda63ed70206 _span_id=f57c007257fee0ed _trace_id=00000000000000000a5af97bffe6a8a2 _tx_duration_ms=0 _tx_start=1659523216 Otherwise, if you configure it to use gelf format, the output will look as follows:\n{\u0026#34;_level_name\u0026#34;: \u0026#34;INFO\u0026#34;, \u0026#34;version\u0026#34;:\u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;:\u0026#34;unknown\u0026#34;, \u0026#34;_tx_start\u0026#34;:1659523295, \u0026#34;_client_ip\u0026#34;: \u0026#34;127.0.0.1\u0026#34;, \u0026#34;_http_method\u0026#34;: \u0026#34;GET\u0026#34;, \u0026#34;_http_path\u0026#34;:\u0026#34;/foo\u0026#34;, \u0026#34;_http_user_agent\u0026#34;: \u0026#34;curl/7.74.0\u0026#34;, \u0026#34;_http_host\u0026#34;: \u0026#34;127.0.0.1:4468\u0026#34;, \u0026#34;_http_scheme\u0026#34;: \u0026#34;http\u0026#34;, \u0026#34;timestamp\u0026#34;: 1659523295, \u0026#34;level\u0026#34;: 6, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;TX started\u0026#34;} .... {\u0026#34;_level_name\u0026#34;: \u0026#34;INFO\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.1\u0026#34;, \u0026#34;host\u0026#34;: \u0026#34;unknown\u0026#34;, \u0026#34;_tx_start\u0026#34;: 1659523295, \u0026#34;_client_ip\u0026#34;: \u0026#34;127.0.0.1\u0026#34;, \u0026#34;_http_method\u0026#34;: \u0026#34;GET\u0026#34;, \u0026#34;_http_path\u0026#34;: \u0026#34;/foo\u0026#34;, \u0026#34;_http_user_agent\u0026#34;: \u0026#34;curl/7.74.0\u0026#34;, \u0026#34;_http_host\u0026#34;: \u0026#34;127.0.0.1:4468\u0026#34;, \u0026#34;_http_scheme\u0026#34;: \u0026#34;http\u0026#34;, \u0026#34;_body_bytes_sent\u0026#34;: 0, \u0026#34;_http_status_code\u0026#34;:200, \u0026#34;_tx_duration_ms\u0026#34;:0, \u0026#34;_subject\u0026#34;: \u0026#34;anonymous\u0026#34;, \u0026#34;_access_granted\u0026#34;: true, \u0026#34;timestamp\u0026#34;:1659523295, \u0026#34;level\u0026#34;: 6, \u0026#34;_parent_id\u0026#34;: \u0026#34;3449bda63ed70206\u0026#34;, \u0026#34;_span_id\u0026#34;: \u0026#34;f57c007257fee0ed\u0026#34;, \u0026#34;_trace_id\u0026#34;: \u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;, \u0026#34;short_message\u0026#34;: \u0026#34;TX finished\u0026#34;} Tracing Heimdall makes use of OpenTelemetry for distributed tracing to support recording of paths taken by requests and supports all environment variables including the defined values according to OpenTelemetry Environment Variables and OpenTelemetry SDK Configuration specifications. In addition to these environment variables, heimdall defines some additional options, which are described below and can be used to tune the behaviour.\nConfiguration By default, tracing is enabled and can be disabled or slightly tuned in the tracing property of heimdall’s configuration supporting the following properties.\nenabled: boolean (optional)\nBy making use of this property, you can configure heimdall to enable or disable tracing. Defaults to true (tracing enabled).\nExample 3. Disabling tracing. tracing: enabled: false span_processor: string (optional)\nWith simple and batch being the available options. By setting this property, you can define how heimdall shall process the created spans. Defaults to batch. This property is only there, as there is no corresponding setting option via OTEL tracing environment variables available.\nExample 4. Setting the span processor to export completed spans in batches. tracing: span_processor: batch Description of the options:\nsimple - Configures heimdall to synchronously export the created spans via configured exporters. This is not recommended for production use as it is slow and has a high computation resource usage overhead. It might be however good for testing, debugging, or showing examples of other features.\nbatch - Configures heimdall to send completed span batches to the exporter. Recommended setting for production use.\nTracing Context Propagation When a request arrives at heimdall, it will create a trace context object based on the received headers, which according to OTEL are the traceparent and tracestate HTTP headers, defined in W3C Trace Context as well as baggage HTTP header, defined in W3C Baggage. The creation of that context, as well as the transformation of it into new HTTP headers, set by heimdall while communicating with further services is named propagation and the components responsible for the creation of such context object are named propagators.\nSince not every service in a multi-service system may set or understand the above OTEL specific HTTP headers (as these might still be using tracing vendor specific headers), interoperability can be achieved by configuring the required propagators by making use of the OTEL_PROPAGATORS environment variable. OTEL defines the following values for this variable:\ntracecontext - W3C Trace Context propagator. Enabled by default, if OTEL_PROPAGATORS is not set.\nbaggage - W3C Baggage propagator. Enabled by default if OTEL_PROPAGATORS is not set.\nb3 - Zipkin B3 Single Header propagator.\nb3multi - Zipkin B3 Multiple Header propagator.\njaeger - Jaeger Header propagator.\nxray - AWS X-Ray Header propagator.\nottrace - OT Trace Header propagator.\nnone - No automatically configured propagator.\nAll of these are supported by heimdall. In addition, following propagators can be configured as well:\ndatadog - Datadog APM Trace Header propagator.[1]\nConfigured propagators are used for inbound, as well as for outbound traffic.\nSpan Exporters Span Exporter handle the delivery of spans to external receivers (collectors, or agents). This is the final component in the trace export pipeline and typically provided by the APM vendor, like Jaeger, Zipkin, Instana, etc. Since not every multi-service system may have an up to day telemetry receiver supporting protocols defined by OTEL, interoperability can be achieved by configuring the required exporters by making use of the OTEL_TRACES_EXPORTER environment variable. OTEL defines the following values for this variable[2]:\notlp - OTLP exporter. Enabled by default if OTEL_TRACES_EXPORTER is not set.\nzipkin - Zipkin exporter to export spans in Zipkin data model.\nnone - No automatically configured exporter for traces.\nAll of these are supported by heimdall. In addition, following exporters can be configured as well:\ninstana - Instana exporter to export spans in Instana data model.[3]\nExample Configuration The environment variables set below configure heimdall to use Jaeger propagator and to export the spans via OTLP over grpc to the collector available under https://collector:4317.\nOTEL_PROPAGATORS=jaeger OTEL_TRACES_EXPORTER=otlp OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://collector:4317 If your environment supports OpenTelemetry and usage of defaults is ok, most probably, the only required environment variable to be set might be the OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.\nMetrics Heimdall makes use of OpenTelemetry to emit metrics. Depending on the configuration, push or pull based metrics export is supported.\nConfiguration As with tracing, the entire configuration happens via environment variables as defined by OpenTelemetry Environment Variables and OpenTelemetry SDK Configuration specifications. The generated metrics can either be exported by pushing these to an OTEL collector (the default behavior). Alternatively, the available metrics can be pulled and are then exported in the (Prometheus style).\nMetrics are generated and exported by default. If this is not desired, you can explicitly disable this behavior within the metrics property of heimdall’s configuration by making use of the following property:\nenabled: boolean (optional)\nBy making use of this property, you can configure heimdall to enable or disable the metrics collection. Defaults to true (metrics exposure is enabled).\nExample 5. Disabling metrics. metrics: enabled: false Metric Exporters By default, metrics are pushed to the OTEL collector using the http/protobuf transport protocol. You can change that behavior by making use of either the OTEL_EXPORTER_OTLP_METRICS_PROTOCOL, or the OTEL_EXPORTER_OTLP_PROTOCOL environment variable.\nTo let heimdall know where to push the metrics to, either OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, or OTEL_EXPORTER_OTLP_ENDPOINT must be defined.\nTo let heimdall expose metrics over a pull based service (Prometheus style), the OTEL_METRICS_EXPORTER environment variable must be set to \u0026#34;prometheus\u0026#34;. In that case heimdall will expose the 127.0.0.1:9464/metrics endpoint which can be queried using the HTTP GET verb. You can change the host and port of that service by making use of the OTEL_EXPORTER_PROMETHEUS_HOST and OTEL_EXPORTER_PROMETHEUS_PORT environment variables.\nYou can also disable metrics export by setting the OTEL_METRICS_EXPORTER environment variable to none.\nAvailable Metrics System metrics according to OpenTelemetry Semantic Conventions for System Metrics.\nProcess and Go runtime metrics according to OpenTelemetry Semantic Conventions for OS Process Metrics.\nInformation about the handled requests on each active service, as well as information about requests in progress according to OpenTelemetry Semantic Conventions for HTTP Metrics and General RPC conventions.\nInformation about the metrics endpoint itself (if enabled), including the number of internal errors encountered while gathering the metrics, number of current inflight and overall scrapes done.\nInformation about expiry for configured certificates.\nAll, but custom metrics adhere to the OpenTelementry semantic conventions. For that reason, only the custom metrics are listed in the table below.\nMetric: certificate.expiry Number of seconds until a certificate used by a particular service (main, management), or mechanism (e.g. jwt finalizer) expires. The metric type is UpDownCounter und the unit is s.\nAttribute Type Description service\nstring\nThe service, the certificate is configured for.\nissuer\nstring\nIssuer DN of the certificate.\nserial_nr\nstring\nThe serial number of the certificate.\nsubject\nstring\nSubject DN of the certificate.\ndns_names\nstring\nDNS entries in the SAN extension\nRuntime Profiling If enabled, heimdall exposes a /debug/pprof HTTP endpoint on port 10251 (See also the configuration options below) on which runtime profiling data in the profile.proto format (also known as pprof format) can be consumed by APM tools, like Google’s pprof, Grafana Phlare, Pyroscope and many more for visualization purposes. Following information is available:\nallocs - A sampling of all past memory allocations.\nblock - Stack traces that led to blocking on synchronization primitives.\ncmdline - The command line invocation of the current program, with arguments separated by NUL bytes.\ngoroutine - Stack traces of all current goroutines.\nheap - A sampling of memory allocations of live objects.\nmutex - Stack traces of holders of contended mutexes.\nprofile - Cpu profile. Profiling lasts for duration specified in seconds parameter, or for 30 seconds if not specified\nsymbol - Looks up the program counters listed in the request, responding with a table mapping program counters to function names.\nthreadcreate - Stack traces that led to the creation of new OS threads.\ntrace - Execution trace in binary form. Tracing lasts for duration specified in seconds parameter, or for 1 second if not specified.\nSee also the API documentation for the documentation of the actual API.\nConfiguration Configuration for this service can be adjusted in the profiling property of heimdall’s configuration by making use of the following properties.\nenabled: boolean (optional)\nBy making use of this property, you can configure heimdall to enable or disable runtime profiling. Defaults to false (profiling disabled).\nExample 6. Enabling profiling. profiling: enabled: true host: string (optional)\nBy making use of this property, you can specify the TCP/IP address on which heimdall should listen for connections from client applications interested in profiling data. The entry 0.0.0.0 allows listening for all IPv4 addresses. Defaults to 127.0.0.1, which allow only local TCP/IP “loopback” connections to be made.\nIf you operate heimdall in a container, you should set this property to a value, which would allow your APM system to scrape this information. Example 7. Configure heimdall to listen on 192.168.2.10. profiling: host: 192.168.2.10 port: integer (optional)\nBy making use of this property, you can specify the TCP port the heimdall should listen on. Defaults to 10251.\nExample 8. Configure heimdall to listen on port 9999 for runtime profiling requests. profiling: port: 9999 1. Datadog supports the OTLP protokoll. For that reason, there is no exporter available. 2. jaeger exporter has been marked as deprecated and is not supported anymore 3. Instana supports the W3C header used by OTEL. For that reason, there is no propagator available. ","description":"To support easier operation and integration in diverse APM products heimdall implements different observability mechanisms. The following sections provide insights about what can be expected.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_logging\"\u003eLogging\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall’s implementation uses \u003ca href=\"https://github.com/rs/zerolog\"\u003ezerolog\u003c/a\u003e - Zero Allocation JSON Logger, which can however also log in plain text. All emitted log statements include information related to distributed tracing (if tracing is enabled) so that not only log statements can be correlated to traces, but also all log statements belonging to single request/transaction can be correlated as well.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eLogging configuration can be adjusted in the \u003ccode\u003elog\u003c/code\u003e property of heimdall’s configuration and supports following properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eformat\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith \u003ccode\u003etext\u003c/code\u003e and \u003ccode\u003egelf\u003c/code\u003e being the available formats. \u003ccode\u003etext\u003c/code\u003e is the default format. And \u003ccode\u003egelf\u003c/code\u003e defines a JSON format adhering to \u003ca href=\"https://docs.graylog.org/v1/docs/gelf\"\u003eGELF\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsage of \u003ccode\u003etext\u003c/code\u003e (default) format is not recommended for production deployments as it requires more computational resources and is hence slow.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Configuring logging to emit logs using GELD format.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eformat\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egelf\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003elevel\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing log levels are available: \u003ccode\u003etrace\u003c/code\u003e, \u003ccode\u003edebug\u003c/code\u003e, \u003ccode\u003einfo\u003c/code\u003e, \u003ccode\u003ewarn\u003c/code\u003e, \u003ccode\u003eerror\u003c/code\u003e, \u003ccode\u003efatal\u003c/code\u003e, \u003ccode\u003epanic\u003c/code\u003e and \u003ccode\u003edisabled\u003c/code\u003e. The last one effectively disables logging. You usually do not want to do this. By default, the level is set to \u003ccode\u003eerror\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003ccode\u003edebug\u003c/code\u003e and \u003ccode\u003etrace\u003c/code\u003e log levels are not meant for production as setting log level to one of these will result in a high log verbosity and also affect performance pretty much. Both are only meant for setup analysis and debugging! \u003ccode\u003etrace\u003c/code\u003e log level will also dump all incoming and outgoing HTTP requests and responses, as well as the contents of objects used in templates. That dump is unedited. That means sensitive data will be available in logs.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nDue to some limitations of the GRPC framework capabilities, setting log level to \u003ccode\u003etrace\u003c/code\u003e will not dump GRPC requests and responses. If you need these for analysis purposes (e.g. when debugging the integration with envoy proxy), you’ll have to set \u003ca href=\"https://pkg.go.dev/net/http?utm_source=godoc#hdr-HTTP_2\"\u003e\u003ccode\u003eGODEBUG\u003c/code\u003e\u003c/a\u003e as well as the \u003ca href=\"https://pkg.go.dev/google.golang.org/grpc/examples/features/debugging#section-readme\"\u003e\u003ccode\u003eGRPC_GO_LOG_VERBOSITY_LEVEL\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"https://pkg.go.dev/google.golang.org/grpc/examples/features/debugging#section-readme\"\u003e\u003ccode\u003eGRPC_GO_LOG_SEVERITY_LEVEL\u003c/code\u003e\u003c/a\u003e environment variables.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Configuring logging to emit logs in debug level.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edebug\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_regular_log_events\"\u003eRegular Log Events\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you configure heimdall to log in \u003ccode\u003etext\u003c/code\u003e format, you can expect output similar to the one shown below:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"log\"\u003e2022-08-03T12:51:48+02:00 INF Opentelemetry tracing initialized.\n2022-08-03T12:51:48+02:00 INF Instantiating in memory cache\n2022-08-03T12:51:48+02:00 DBG Creating rule set event queue.\n2022-08-03T12:51:48+02:00 INF Loading pipeline definitions\n2022-08-03T12:51:48+02:00 DBG Loading definitions for authenticators\n2022-08-03T12:51:48+02:00 DBG Loading pipeline definition id=anonymous_authenticator type=anonymous\n...\n2022-08-03T12:51:52+02:00 DBG Decision endpoint called\n2022-08-03T12:51:52+02:00 DBG Executing default rule\n2022-08-03T12:51:52+02:00 DBG Authenticating using anonymous authenticator\n2022-08-03T12:51:52+02:00 DBG Finalizing using JWT finalizer\n2022-08-03T12:51:52+02:00 DBG Generating new JWT\n2022-08-03T12:51:52+02:00 DBG Finalizing request\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsage of this format is not recommended for production deployments as it requires more computational resources and is hence slow.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOtherwise, if you configure it to use \u003ccode\u003egelf\u003c/code\u003e (see \u003ca href=\"https://docs.graylog.org/v1/docs/gelf\"\u003eGELF\u003c/a\u003e for format details) format, the output will look as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;INFO\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Opentracing tracer initialized.\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;INFO\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Instantiating in memory cache\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Creating rule set event queue.\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;INFO\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Loading pipeline definitions\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Loading definitions for authenticators\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;anonymous_authenticator\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;type\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;anonymous\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523288\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Loading pipeline definition\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\n\u003c/span\u003e\u003cspan class=\"err\"\u003e...\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Decision endpoint called\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Executing default rule\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Authenticating using anonymous authenticator\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Finalizing using JWT finalizer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Generating new JWT\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;DEBUG\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Finalizing request\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach log statement does also include the following fields in both log formats for incoming requests if tracing is enabled:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_trace_id\u003c/code\u003e - The trace id as defined by OpenTelemetry.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_span_id\u003c/code\u003e - The span id as defined by OpenTelemetry of the current transaction.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_parent_id\u003c/code\u003e - The span id of the callee, which started the given transaction. Only present if the callee set the corresponding tracing header.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_access_log_events\"\u003eAccess Log Events\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition to regular logs, heimdall emits access logs. These events are always emitted regardless the configured log level and the log level of these events in the log output is always \u003ccode\u003eINFO\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach request to any of heimdall’s endpoints will result in two access events:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eevent describing the start of the transaction, and an\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eevent describing the finalization of the transaction.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing are the fields, which are always set for both events:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_tx_start\u003c/code\u003e - Timestamp in Unix epoch format, when the transaction started.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_client_ip\u003c/code\u003e - The IP of the client of the request.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the event has been emitted for an HTTP request, following fields are set as well:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_method\u003c/code\u003e - The HTTP method used by the client while calling heimdall’s endpoint.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_path\u003c/code\u003e - The used HTTP path.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_user_agent\u003c/code\u003e - The agent used by the client. The value is taken from the HTTP \u0026#34;User-Agent\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_host\u003c/code\u003e - The host part of the URI, the client is using while communicating with Heimdall.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_scheme\u003c/code\u003e - The scheme part of the URI, the client is using while communicating with Heimdall.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the event has been emitted for a GRPC request, following fields are set:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_grpc_method\u003c/code\u003e - The full GRPC method used.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the request comes from an intermediary, like e.g. an API Gateway and heimdall is configured to trust that \u0026#34;proxy\u0026#34; (see \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003e\u003ccode\u003etrusted_proxies\u003c/code\u003e configuration\u003c/a\u003e), then following fields will be part of the events as well if the corresponding HTTP headers were sent.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_x_forwarded_proto\u003c/code\u003e - The value of the \u0026#34;X-Forwarded-Proto\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_x_forwarded_host\u003c/code\u003e - The value of the \u0026#34;X-Forwarded-Host\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_x_forwarded_uri\u003c/code\u003e - The value of the \u0026#34;X-Forwarded-Uri\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_x_forwarded_for\u003c/code\u003e - The value of the \u0026#34;X-Forwarded-For\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_forwarded\u003c/code\u003e - The value of the \u0026#34;Forwarded\u0026#34; header.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing are the fields, which are set in the transaction finalization event in addition:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_body_bytes_sent\u003c/code\u003e - The length of the response body.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_tx_duration_ms\u003c/code\u003e - The duration of the transaction in milliseconds. If heimdall is operated in proxy mode, it will also include the time used to communicate with the upstream service.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_access_granted\u003c/code\u003e - Set either to \u003ccode\u003etrue\u003c/code\u003e or \u003ccode\u003efalse\u003c/code\u003e, indicating whether heimdall granted access or not.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_subject\u003c/code\u003e - The subject identifier if the access was granted.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_error\u003c/code\u003e - The information about an error, which e.g. led to the denial of the request.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the finalization event has been emitted for an HTTP request, following fields are set as well:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_http_status_code\u003c/code\u003e - The numeric HTTP response status code\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the finalization event has been emitted for a GRPC request, following fields are set:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_grpc_status_code\u003c/code\u003e - The numeric GRPC status code.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing are the fields, which are set if tracing is enabled:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_trace_id\u003c/code\u003e - The trace id as defined by OpenTelemetry.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_span_id\u003c/code\u003e - The span id as defined by OpenTelemetry of the current transaction.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e_parent_id\u003c/code\u003e - The span id of the callee, which started the given transaction. Only present if the callee set the corresponding tracing header.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you configure heimdall to log in \u003ccode\u003etext\u003c/code\u003e format, you can expect output as shown below:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003e2022-08-03T12:40:16+02:00 INF TX started _client_ip=127.0.0.1 _http_host=127.0.0.1:4468 _http_method=GET\n _http_path=/foo _http_scheme=http _http_user_agent=curl/7.74.0 _parent_id=3449bda63ed70206\n _span_id=f57c007257fee0ed _trace_id=00000000000000000a5af97bffe6a8a2 _tx_start=1659523216\n\n....\n\n2022-08-03T12:40:16+02:00 INF TX finished _access_granted=true _body_bytes_sent=0 _client_ip=127.0.0.1\n _http_host=127.0.0.1:4468 _http_method=GET _http_path=/foo _http_scheme=http _http_status_code=202\n _http_user_agent=curl/7.74.0 _subject=anonymous _parent_id=3449bda63ed70206 _span_id=f57c007257fee0ed\n _trace_id=00000000000000000a5af97bffe6a8a2 _tx_duration_ms=0 _tx_start=1659523216\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOtherwise, if you configure it to use \u003ccode\u003egelf\u003c/code\u003e format, the output will look as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;INFO\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_tx_start\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_client_ip\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;127.0.0.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_method\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;GET\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_path\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;/foo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_user_agent\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;curl/7.74.0\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;127.0.0.1:4468\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_scheme\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;http\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;TX started\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\n\u003c/span\u003e\u003cspan class=\"err\"\u003e....\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\n\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_level_name\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;INFO\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;version\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unknown\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_tx_start\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_client_ip\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;127.0.0.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_method\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;GET\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_path\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;/foo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_user_agent\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;curl/7.74.0\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_host\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;127.0.0.1:4468\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_scheme\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;http\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_body_bytes_sent\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_http_status_code\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e200\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_tx_duration_ms\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_subject\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;anonymous\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_access_granted\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1659523295\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;level\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_parent_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3449bda63ed70206\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_span_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;f57c007257fee0ed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;_trace_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;00000000000000000a5af97bffe6a8a2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;short_message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;TX finished\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_tracing\"\u003eTracing\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall makes use of \u003ca href=\"https://opentelemetry.io/\"\u003eOpenTelemetry\u003c/a\u003e for distributed tracing to support recording of paths taken by requests and supports all environment variables including the defined values according to \u003ca href=\"https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/\"\u003eOpenTelemetry Environment Variables\u003c/a\u003e and \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/\"\u003eOpenTelemetry SDK Configuration\u003c/a\u003e specifications. In addition to these environment variables, heimdall defines some additional options, which are described below and can be used to tune the behaviour.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_2\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy default, tracing is enabled and can be disabled or slightly tuned in the \u003ccode\u003etracing\u003c/code\u003e property of heimdall’s configuration supporting the following properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eenabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can configure heimdall to enable or disable tracing. Defaults to \u003ccode\u003etrue\u003c/code\u003e (tracing enabled).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Disabling tracing.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003espan_processor\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith \u003ccode\u003esimple\u003c/code\u003e and \u003ccode\u003ebatch\u003c/code\u003e being the available options. By setting this property, you can define how heimdall shall process the created spans. Defaults to \u003ccode\u003ebatch\u003c/code\u003e. This property is only there, as there is no corresponding setting option via OTEL tracing environment variables available.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Setting the span processor to export completed spans in batches.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003espan_processor\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebatch\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDescription of the options:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003esimple\u003c/code\u003e - Configures heimdall to synchronously export the created spans via configured exporters. This is not recommended for production use as it is slow and has a high computation resource usage overhead. It might be however good for testing, debugging, or showing examples of other features.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ebatch\u003c/code\u003e - Configures heimdall to send completed span batches to the exporter. Recommended setting for production use.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_tracing_context_propagation\"\u003eTracing Context Propagation\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhen a request arrives at heimdall, it will create a trace context object based on the received headers, which according to OTEL are the \u003ccode\u003etraceparent\u003c/code\u003e and \u003ccode\u003etracestate\u003c/code\u003e HTTP headers, defined in \u003ca href=\"https://www.w3.org/TR/trace-context/\"\u003eW3C Trace Context\u003c/a\u003e as well as \u003ccode\u003ebaggage\u003c/code\u003e HTTP header, defined in \u003ca href=\"https://www.w3.org/TR/baggage/\"\u003eW3C Baggage\u003c/a\u003e. The creation of that context, as well as the transformation of it into new HTTP headers, set by heimdall while communicating with further services is named propagation and the components responsible for the creation of such context object are named propagators.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince not every service in a multi-service system may set or understand the above OTEL specific HTTP headers (as these might still be using tracing vendor specific headers), interoperability can be achieved by configuring the required propagators by making use of the \u003ccode\u003eOTEL_PROPAGATORS\u003c/code\u003e environment variable. OTEL defines the following values for this variable:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etracecontext\u003c/code\u003e - \u003ca href=\"https://www.w3.org/TR/trace-context/\"\u003eW3C Trace Context\u003c/a\u003e propagator. Enabled by default, if \u003ccode\u003eOTEL_PROPAGATORS\u003c/code\u003e is not set.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ebaggage\u003c/code\u003e - \u003ca href=\"https://www.w3.org/TR/baggage/\"\u003eW3C Baggage\u003c/a\u003e propagator. Enabled by default if \u003ccode\u003eOTEL_PROPAGATORS\u003c/code\u003e is not set.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eb3\u003c/code\u003e - \u003ca href=\"https://github.com/openzipkin/b3-propagation#single-header\"\u003eZipkin B3 Single Header\u003c/a\u003e propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eb3multi\u003c/code\u003e - \u003ca href=\"https://github.com/openzipkin/b3-propagation#multiple-headers\"\u003eZipkin B3 Multiple Header\u003c/a\u003e propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ejaeger\u003c/code\u003e - \u003ca href=\"https://www.jaegertracing.io/docs/1.38/client-libraries/#propagation-format\"\u003eJaeger Header\u003c/a\u003e propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003exray\u003c/code\u003e - \u003ca href=\"https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader\"\u003eAWS X-Ray Header\u003c/a\u003e propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eottrace\u003c/code\u003e - \u003ca href=\"https://github.com/opentracing?q=basic\u0026amp;type=\u0026amp;language=\"\u003eOT Trace Header\u003c/a\u003e propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003enone\u003c/code\u003e - No automatically configured propagator.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll of these are supported by heimdall. In addition, following propagators can be configured as well:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003edatadog\u003c/code\u003e - \u003ca href=\"https://www.datadoghq.com/product/apm/\"\u003eDatadog APM Trace Header\u003c/a\u003e propagator.\u003csup class=\"footnote\"\u003e[\u003ca id=\"_footnoteref_1\" class=\"footnote\" href=\"#_footnotedef_1\" title=\"View footnote.\"\u003e1\u003c/a\u003e]\u003c/sup\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfigured propagators are used for inbound, as well as for outbound traffic.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_span_exporters\"\u003eSpan Exporters\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpan Exporter handle the delivery of spans to external receivers (collectors, or agents). This is the final component in the trace export pipeline and typically provided by the APM vendor, like Jaeger, Zipkin, Instana, etc. Since not every multi-service system may have an up to day telemetry receiver supporting protocols defined by OTEL, interoperability can be achieved by configuring the required exporters by making use of the \u003ccode\u003eOTEL_TRACES_EXPORTER\u003c/code\u003e environment variable. OTEL defines the following values for this variable\u003csup class=\"footnote\"\u003e[\u003ca id=\"_footnoteref_2\" class=\"footnote\" href=\"#_footnotedef_2\" title=\"View footnote.\"\u003e2\u003c/a\u003e]\u003c/sup\u003e:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eotlp\u003c/code\u003e - \u003ca href=\"https://opentelemetry.io/docs/reference/specification/protocol/otlp/\"\u003eOTLP\u003c/a\u003e exporter. Enabled by default if \u003ccode\u003eOTEL_TRACES_EXPORTER\u003c/code\u003e is not set.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ezipkin\u003c/code\u003e - \u003ca href=\"https://zipkin.io/zipkin-api/\"\u003eZipkin\u003c/a\u003e exporter to export spans in Zipkin data model.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003enone\u003c/code\u003e - No automatically configured exporter for traces.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll of these are supported by heimdall. In addition, following exporters can be configured as well:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003einstana\u003c/code\u003e - \u003ca href=\"https://www.instana.com/\"\u003eInstana\u003c/a\u003e exporter to export spans in Instana data model.\u003csup class=\"footnote\"\u003e[\u003ca id=\"_footnoteref_3\" class=\"footnote\" href=\"#_footnotedef_3\" title=\"View footnote.\"\u003e3\u003c/a\u003e]\u003c/sup\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_example_configuration\"\u003eExample Configuration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe environment variables set below configure heimdall to use Jaeger propagator and to export the spans via OTLP over grpc to the collector available under \u003ccode\u003ehttps://collector:4317\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003eOTEL_PROPAGATORS=jaeger\nOTEL_TRACES_EXPORTER=otlp\nOTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc\nOTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://collector:4317\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf your environment supports OpenTelemetry and usage of defaults is ok, most probably, the only required environment variable to be set might be the \u003ccode\u003eOTEL_EXPORTER_OTLP_TRACES_ENDPOINT\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_metrics\"\u003eMetrics\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall makes use of \u003ca href=\"https://opentelemetry.io/\"\u003eOpenTelemetry\u003c/a\u003e to emit metrics. Depending on the configuration, push or pull based metrics export is supported.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_3\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with tracing, the entire configuration happens via environment variables as defined by \u003ca href=\"https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/\"\u003eOpenTelemetry Environment Variables\u003c/a\u003e and \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/\"\u003eOpenTelemetry SDK Configuration\u003c/a\u003e specifications. The generated metrics can either be exported by pushing these to an OTEL collector (the default behavior). Alternatively, the available metrics can be pulled and are then exported in the (\u003ca href=\"https://grafana.com/oss/prometheus/\"\u003ePrometheus\u003c/a\u003e style).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eMetrics are generated and exported by default. If this is not desired, you can explicitly disable this behavior within the \u003ccode\u003emetrics\u003c/code\u003e property of heimdall’s configuration by making use of the following property:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eenabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can configure heimdall to enable or disable the metrics collection. Defaults to \u003ccode\u003etrue\u003c/code\u003e (metrics exposure is enabled).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Disabling metrics.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emetrics\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_metric_exporters\"\u003eMetric Exporters\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy default, metrics are pushed to the OTEL collector using the \u003ccode\u003ehttp/protobuf\u003c/code\u003e transport protocol. You can change that behavior by making use of either the \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_metrics_protocol\"\u003e\u003ccode\u003eOTEL_EXPORTER_OTLP_METRICS_PROTOCOL\u003c/code\u003e\u003c/a\u003e, or the \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_protocol\"\u003e\u003ccode\u003eOTEL_EXPORTER_OTLP_PROTOCOL\u003c/code\u003e\u003c/a\u003e environment variable.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo let heimdall know where to push the metrics to, either \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_metrics_endpoint\"\u003e\u003ccode\u003eOTEL_EXPORTER_OTLP_METRICS_ENDPOINT\u003c/code\u003e\u003c/a\u003e, or \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_endpoint\"\u003e\u003ccode\u003eOTEL_EXPORTER_OTLP_ENDPOINT\u003c/code\u003e\u003c/a\u003e must be defined.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo let heimdall expose metrics over a pull based service (\u003ca href=\"https://grafana.com/oss/prometheus/\"\u003ePrometheus\u003c/a\u003e style), the \u003ca href=\"https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_metrics_exporter\"\u003e\u003ccode\u003eOTEL_METRICS_EXPORTER\u003c/code\u003e\u003c/a\u003e environment variable must be set to \u003ccode\u003e\u0026#34;prometheus\u0026#34;\u003c/code\u003e. In that case heimdall will expose the \u003ccode\u003e127.0.0.1:9464/metrics\u003c/code\u003e endpoint which can be queried using the HTTP GET verb. You can change the host and port of that service by making use of the \u003ca href=\"https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#prometheus-exporter\"\u003e\u003ccode\u003eOTEL_EXPORTER_PROMETHEUS_HOST\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#prometheus-exporter\"\u003e\u003ccode\u003eOTEL_EXPORTER_PROMETHEUS_PORT\u003c/code\u003e\u003c/a\u003e environment variables.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can also disable metrics export by setting the \u003ccode\u003eOTEL_METRICS_EXPORTER\u003c/code\u003e environment variable to \u003ccode\u003enone\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_available_metrics\"\u003eAvailable Metrics\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eSystem metrics according to \u003ca href=\"https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/system-metrics/\"\u003eOpenTelemetry Semantic Conventions for System Metrics\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eProcess and Go runtime metrics according to \u003ca href=\"https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/process-metrics/\"\u003eOpenTelemetry Semantic Conventions for OS Process Metrics\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eInformation about the handled requests on each active service, as well as information about requests in progress according to OpenTelemetry \u003ca href=\"https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/http-metrics/\"\u003eSemantic Conventions for HTTP Metrics\u003c/a\u003e and \u003ca href=\"https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/rpc-metrics/\"\u003eGeneral RPC conventions\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eInformation about the metrics endpoint itself (if enabled), including the number of internal errors encountered while gathering the metrics, number of current inflight and overall scrapes done.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eInformation about expiry for configured certificates.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll, but custom metrics adhere to the \u003ca href=\"https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/\"\u003eOpenTelementry semantic conventions\u003c/a\u003e. For that reason, only the custom metrics are listed in the table below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect3\"\u003e\n\u003ch4 id=\"_metric_certificate_expiry\"\u003eMetric: \u003ccode\u003ecertificate.expiry\u003c/code\u003e\u003c/h4\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNumber of seconds until a certificate used by a particular service (main, management), or mechanism (e.g. jwt finalizer) expires. The metric type is UpDownCounter und the unit is s.\u003c/p\u003e\n\u003c/div\u003e\n\u003ctable class=\"tableblock frame-all grid-all stretch\"\u003e\n\u003ccolgroup\u003e\n\u003ccol style=\"width: 25%;\"/\u003e\n\u003ccol style=\"width: 12.5%;\"/\u003e\n\u003ccol style=\"width: 62.5%;\"/\u003e\n\u003c/colgroup\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eAttribute\u003c/strong\u003e\u003c/th\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eType\u003c/strong\u003e\u003c/th\u003e\n\u003cth class=\"tableblock halign-left valign-top\"\u003e\u003cstrong\u003eDescription\u003c/strong\u003e\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ccode\u003eservice\u003c/code\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003estring\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eThe service, the certificate is configured for.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ccode\u003eissuer\u003c/code\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003estring\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eIssuer DN of the certificate.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ccode\u003eserial_nr\u003c/code\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003estring\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eThe serial number of the certificate.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ccode\u003esubject\u003c/code\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003estring\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eSubject DN of the certificate.\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003e\u003ccode\u003edns_names\u003c/code\u003e\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003estring\u003c/p\u003e\u003c/td\u003e\n\u003ctd class=\"tableblock halign-left valign-top\"\u003e\u003cp class=\"tableblock\"\u003eDNS entries in the SAN extension\u003c/p\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_runtime_profiling\"\u003eRuntime Profiling\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf enabled, heimdall exposes a \u003ccode\u003e/debug/pprof\u003c/code\u003e HTTP endpoint on port \u003ccode\u003e10251\u003c/code\u003e (See also the configuration options below) on which runtime profiling data in the \u003ccode\u003eprofile.proto\u003c/code\u003e format (also known as \u003ccode\u003epprof\u003c/code\u003e format) can be consumed by APM tools, like \u003ca href=\"https://github.com/google/pprof\"\u003eGoogle’s pprof\u003c/a\u003e, \u003ca href=\"https://grafana.com/oss/phlare/\"\u003eGrafana Phlare\u003c/a\u003e, \u003ca href=\"https://pyroscope.io/\"\u003ePyroscope\u003c/a\u003e and many more for visualization purposes. Following information is available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eallocs\u003c/code\u003e - A sampling of all past memory allocations.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eblock\u003c/code\u003e - Stack traces that led to blocking on synchronization primitives.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ecmdline\u003c/code\u003e - The command line invocation of the current program, with arguments separated by NUL bytes.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003egoroutine\u003c/code\u003e - Stack traces of all current goroutines.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eheap\u003c/code\u003e - A sampling of memory allocations of live objects.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emutex\u003c/code\u003e - Stack traces of holders of contended mutexes.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eprofile\u003c/code\u003e - Cpu profile. Profiling lasts for duration specified in \u003ccode\u003eseconds\u003c/code\u003e parameter, or for 30 seconds if not specified\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003esymbol\u003c/code\u003e - Looks up the program counters listed in the request, responding with a table mapping program counters to function names.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ethreadcreate\u003c/code\u003e - Stack traces that led to the creation of new OS threads.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etrace\u003c/code\u003e - Execution trace in binary form. Tracing lasts for duration specified in \u003ccode\u003eseconds\u003c/code\u003e parameter, or for 1 second if not specified.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSee also the \u003ca href=\"/openapi/#tag/Profiling\"\u003eAPI\u003c/a\u003e documentation for the documentation of the actual API.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_4\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration for this service can be adjusted in the \u003ccode\u003eprofiling\u003c/code\u003e property of heimdall’s configuration by making use of the following properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eenabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can configure heimdall to enable or disable runtime profiling. Defaults to \u003ccode\u003efalse\u003c/code\u003e (profiling disabled).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 6. Enabling profiling.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eprofiling\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehost\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can specify the TCP/IP address on which heimdall should listen for connections from client applications interested in profiling data. The entry \u003ccode\u003e0.0.0.0\u003c/code\u003e allows listening for all IPv4 addresses. Defaults to \u003ccode\u003e127.0.0.1\u003c/code\u003e, which allow only local TCP/IP “loopback” connections to be made.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you operate heimdall in a container, you should set this property to a value, which would allow your APM system to scrape this information.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 7. Configure heimdall to listen on \u003ccode\u003e192.168.2.10\u003c/code\u003e.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eprofiling\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e192.168.2.10\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eport\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can specify the TCP port the heimdall should listen on. Defaults to \u003ccode\u003e10251\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 8. Configure heimdall to listen on port \u003ccode\u003e9999\u003c/code\u003e for runtime profiling requests.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eprofiling\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e9999\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"footnotes\"\u003e\n\u003chr/\u003e\n\u003cdiv class=\"footnote\" id=\"_footnotedef_1\"\u003e\n\u003ca href=\"#_footnoteref_1\"\u003e1\u003c/a\u003e. Datadog supports the OTLP protokoll. For that reason, there is no exporter available.\n\u003c/div\u003e\n\u003cdiv class=\"footnote\" id=\"_footnotedef_2\"\u003e\n\u003ca href=\"#_footnoteref_2\"\u003e2\u003c/a\u003e. jaeger exporter has been marked as deprecated and is not supported anymore\n\u003c/div\u003e\n\u003cdiv class=\"footnote\" id=\"_footnotedef_3\"\u003e\n\u003ca href=\"#_footnoteref_3\"\u003e3\u003c/a\u003e. Instana supports the W3C header used by OTEL. For that reason, there is no propagator available.\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Operations"],"tags":null,"title":"Observability ","url":"/docs/operations/observability/"},{"categories":null,"content":" Even some default caching is in place, and you can instruct heimdall to cache particular data for some amount of time, like e.g how long to cache the response from the JWKS endpoint when using the JWT Authenticator, all these options require a caching backend to be available. Otherwise, the corresponding configurations do not have any effect.\nConfiguration of that backend happens by making use of the cache property in heimdall’s configuration, which supports the following options:\ntype - The mandatory specific type of the cache backend.\nconfig - A cache backend specific configuration if required by the type.\nNoop Backend With that backend configured, caching is disabled entirely. That means any cache settings on any mechanism do not have any effect. Even those, applied by heimdall by default are disabled.\nTo configure this backend, you have to specify noop as type. No further configuration is supported. Here an example:\ncache: type: noop In-Memory Backend This backend manages the cached items in memory of heimdall’s process.\nTo configure it, you have to specify in-memory as type. No further configuration is supported. Here an example:\ncache: type: in-memory By default, heimdall makes use of this backend. Redis Backends As the name of this chapter implies, there are multiple backend types, you can configure to make use of Redis as distributed cache:\na Redis single instance,\na Redis cluster and\na Redis sentinel.\nAll types use pipelining to increase performance and do also make use of client side caching if not disabled (see also below).\nCommon Settings All Redis cache backend types support the following configuration options:\ncredentials: Credentials (optional)\nHerewith you can define the credentials to be used for connection purposes. Following settings are possible\npath: string (mandatory)\nPath to a JSON/YAML file with credentials (supports watching for secrets rotation) specifying the username and password as shown below.\n# contents of a credentials file username: Aladdin password: SesameOpen! If used no other properties can be configured for credentials.\nusername: string(optional)\nThe username to use to connect to the Redis DB/Cluster, and\npassword: string(mandatory)\nThe password to be used\nclient_cache: ClientCache (optional)\nConfigurs the client cache to reduce roundtrip time. Following settings are possible:\ndisabled: boolean (optional)\nWhether the client cache should be disabled. Defaults to false.\nttl: Duration (optional)\nSpecifies the maximum TTL on the client side for all used keys. If the key’s TTL on the server is smaller than the client side TTL, the client side TTL will be capped.\nsize_per_connection: ByteSize (optional)\nClient side cache size that bind to each TCP connection to a single redis instance. Defaults to 128MB.\nbuffer_limit: BufferLimit (optional)\nRead and write buffer limits for established connections. Following configuration properties are supported:\nread: ByteSize (optional)\nThe maximum size for the read buffer allowed to read the full request including body. Defaults to 0.5MB.\nwrite: ByteSize (optional)\nThe maximum size for the write buffer of the response. Defaults to 0.5MB.\ntimeout: Timeout (optional)\nBy using this property you can override the default connection timeouts. Following properties are supported:\nwrite: Duration (optional)\nThe maximum duration before timing out writes of the response. Defaults to 150s.\nmax_flush_delay: Duration (optional)\nData flush delay. When greater than zero, pauses pipeline write loop for some time (not larger than the specified delay) after each flushing of data to the connection. This gives pipeline a chance to collect more commands to send to Redis. Adding this delay increases latency, reduces throughput, but in most cases may significantly reduce application and Redis CPU utilization due to less executed system calls. By default, the data is flushed to the connection without extra delays. Depending on network latency and application-specific conditions the value of max_flush_delay may vary, something like 20 µs should not affect latency/throughput a lot but still produce notable CPU usage reduction under load. Defaults to 0s.\ntls: TLS (optional)\nTLS settings. By default, the communication to Redis happens over TLS. This requires however a properly configured trust store, as otherwise heimdall won’t trust the certificates used by the Redis services. In addition to the referenced configuration options, you can also make use of the following properties:\ndisabled: boolean (optional)\nDisables TLS. Defaults to false.\nThis property can be set to true only if heimdall is started with the --insecure-skip-egress-tls-enforcement flag, which allows insecure communication with any configured service. Redis Single Instance As the name implies, this type supports configuration of a single instance Redis DB.\nTo use it, you have to specify redis as type. Configuration is mandatory with following options in addition to the configuration options described in Common Settings.\naddress: string (mandatory)\nThe Redis instance address to connect to.\ndb: integer (optional)\nRedis DB ID to use. Defaults to 0.\nHere an example:\ncache: type: redis config: address: foo:12345 credentials: path: /path/to/credentials.yaml client_cache: ttl: 10m size_per_connection: 128MB buffer_limit: read: 1MB write: 1MB timeout: write: 150s max_flush_delay: 20us tls: # TLS client auth is used here key_store: path: /path/to/keystore/file.pem password: ${MY_REDIS_CLIENT_KEYSTORE} min_version: TLS1.2 Redis Cluster As the name implies, this type supports configuration of a Redis cluster.\nTo use it, you have to specify redis-cluster as type. Configuration is mandatory with following options in addition to the configuration options described in Common Settings.\nnodes: array of strings (mandatory)\nThe addresses of Redis nodes to connect to.\nHere an example:\ncache: type: redis-cluster config: nodes: - foo:1234 - bar:1234 credentials: username: ${MY_REDIS_USER} password: ${MY_REDIS_PASSWORD} Redis Sentinel As the name implies, this type supports configuration of a Redis sentinel.\nTo use it, you have to specify redis-sentinel as type. Configuration is mandatory with following options in addition to the configuration options described in Common Settings.\nnodes: array of strings (mandatory)\nThe addresses of Redis sentinel nodes to connect to.\ndb: integer (optional)\nRedis DB ID to use. Defaults to 0.\nmaster: string (mandatory)\nSentinel master set name\nSame credentials are used to connect to the sentinel service and to the Redis DB instances. This is also true if TLS client authentication is used. Here an example:\ncache: type: redis-sentinel config: nodes: - foo:1234 - bar:1234 db: 0 master: whatever credentials: path: /path/to/credentials.yaml ","description":"To increase performance, you can configure heimdall to make use of caching. Indeed, caching is even done by default in some places.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEven some default caching is in place, and you can instruct heimdall to cache particular data for some amount of time, like e.g how long to cache the response from the JWKS endpoint when using the \u003ca href=\"/docs/mechanisms/authenticators/#_jwt\"\u003eJWT Authenticator\u003c/a\u003e, all these options require a caching backend to be available. Otherwise, the corresponding configurations do not have any effect.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration of that backend happens by making use of the \u003ccode\u003ecache\u003c/code\u003e property in heimdall’s configuration, which supports the following options:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e - The mandatory specific type of the cache backend.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003econfig\u003c/code\u003e - A cache backend specific configuration if required by the type.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_noop_backend\"\u003eNoop Backend\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWith that backend configured, caching is disabled entirely. That means any cache settings on any mechanism do not have any effect. Even those, applied by heimdall by default are disabled.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo configure this backend, you have to specify \u003ccode\u003enoop\u003c/code\u003e as type. No further configuration is supported. Here an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_in_memory_backend\"\u003eIn-Memory Backend\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis backend manages the cached items in memory of heimdall’s process.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo configure it, you have to specify \u003ccode\u003ein-memory\u003c/code\u003e as type. No further configuration is supported. Here an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ein-memory\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nBy default, heimdall makes use of this backend.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_redis_backends\"\u003eRedis Backends\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name of this chapter implies, there are multiple backend types, you can configure to make use of \u003ca href=\"https://redis.io/\"\u003eRedis\u003c/a\u003e as distributed cache:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ea \u003ca href=\"#_redis_single_instance\"\u003eRedis single instance\u003c/a\u003e,\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea \u003ca href=\"#_redis_cluster\"\u003eRedis cluster\u003c/a\u003e and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea \u003ca href=\"#_redis_sentinel\"\u003eRedis sentinel\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll types use pipelining to increase performance and do also make use of client side caching if not disabled (see also below).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_common_settings\"\u003eCommon Settings\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAll Redis cache backend types support the following configuration options:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecredentials\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eCredentials\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHerewith you can define the credentials to be used for connection purposes. Following settings are possible\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epath\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePath to a JSON/YAML file with credentials (supports watching for secrets rotation) specifying the \u003ccode\u003eusername\u003c/code\u003e and \u003ccode\u003epassword\u003c/code\u003e as shown below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# contents of a credentials file\u003c/span\u003e\n\u003cspan class=\"na\"\u003eusername\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAladdin\u003c/span\u003e\n\u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSesameOpen!\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf used no other properties can be configured for credentials.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eusername\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e(optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe username to use to connect to the Redis DB/Cluster, and\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epassword\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e(mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe password to be used\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclient_cache\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eClientCache\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfigurs the client cache to reduce roundtrip time. Following settings are possible:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edisabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhether the client cache should be disabled. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ettl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies the maximum TTL on the client side for all used keys. If the key’s TTL on the server is smaller than the client side TTL, the client side TTL will be capped.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esize_per_connection\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eClient side cache size that bind to each TCP connection to a single redis instance. Defaults to 128MB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebuffer_limit\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eBufferLimit\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRead and write buffer limits for established connections. Following configuration properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eread\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size for the read buffer allowed to read the full request including body. Defaults to 0.5MB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size for the write buffer of the response. Defaults to 0.5MB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etimeout\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eTimeout\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy using this property you can override the default connection timeouts. Following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum duration before timing out writes of the response. Defaults to 150s.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_flush_delay\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eData flush delay. When greater than zero, pauses pipeline write loop for some time (not larger than the specified delay) after each flushing of data to the connection. This gives pipeline a chance to collect more commands to send to Redis. Adding this delay increases latency, reduces throughput, but in most cases may significantly reduce application and Redis CPU utilization due to less executed system calls. By default, the data is flushed to the connection without extra delays. Depending on network latency and application-specific conditions the value of max_flush_delay may vary, something like 20 µs should not affect latency/throughput a lot but still produce notable CPU usage reduction under load. Defaults to 0s.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etls\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_tls\"\u003eTLS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTLS settings. By default, the communication to Redis happens over TLS. This requires however a properly configured \u003ca href=\"/docs/operations/security/#_tls_trust_store\"\u003etrust store\u003c/a\u003e, as otherwise heimdall won’t trust the certificates used by the Redis services. In addition to the referenced configuration options, you can also make use of the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edisabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDisables TLS. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis property can be set to \u003ccode\u003etrue\u003c/code\u003e only if heimdall is started with the \u003ccode\u003e--insecure-skip-egress-tls-enforcement\u003c/code\u003e flag, which allows insecure communication with any configured service.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_redis_single_instance\"\u003eRedis Single Instance\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this type supports configuration of a single instance Redis DB.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo use it, you have to specify \u003ccode\u003eredis\u003c/code\u003e as type. Configuration is mandatory with following options in addition to the configuration options described in \u003ca href=\"#_common_settings\"\u003eCommon Settings\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eaddress\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe Redis instance address to connect to.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edb\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRedis DB ID to use. Defaults to 0.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredis\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaddress\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo:12345\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecredentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/credentials.yaml\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10m\u003c/span\u003e\n \u003cspan class=\"na\"\u003esize_per_connection\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e128MB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuffer_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1MB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1MB\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e150s\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_flush_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e20us\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# TLS client auth is used here\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/keystore/file.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${MY_REDIS_CLIENT_KEYSTORE}\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_redis_cluster\"\u003eRedis Cluster\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this type supports configuration of a Redis cluster.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo use it, you have to specify \u003ccode\u003eredis-cluster\u003c/code\u003e as type. Configuration is mandatory with following options in addition to the configuration options described in \u003ca href=\"#_common_settings\"\u003eCommon Settings\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003enodes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003earray of strings\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe addresses of Redis nodes to connect to.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredis-cluster\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003enodes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo:1234\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar:1234\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecredentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eusername\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${MY_REDIS_USER}\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${MY_REDIS_PASSWORD}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_redis_sentinel\"\u003eRedis Sentinel\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this type supports configuration of a Redis sentinel.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo use it, you have to specify \u003ccode\u003eredis-sentinel\u003c/code\u003e as type. Configuration is mandatory with following options in addition to the configuration options described in \u003ca href=\"#_common_settings\"\u003eCommon Settings\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003enodes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003earray of strings\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe addresses of Redis sentinel nodes to connect to.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edb\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRedis DB ID to use. Defaults to 0.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emaster\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSentinel master set name\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nSame credentials are used to connect to the sentinel service and to the Redis DB instances. This is also true if TLS client authentication is used.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredis-sentinel\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003enodes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo:1234\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar:1234\u003c/span\u003e\n \u003cspan class=\"na\"\u003edb\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e0\u003c/span\u003e\n \u003cspan class=\"na\"\u003emaster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ewhatever\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecredentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/credentials.yaml\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Operations"],"tags":null,"title":"Caching","url":"/docs/operations/cache/"},{"categories":null,"content":" Defaults The following configurations and behaviors are enforced by default:\nAll inbound communication must use TLS. TLS configuration is required for all services and endpoints exposed by heimdall. This enforcement can be disabled (not recommended) by starting Heimdall with the --insecure-skip-ingress-tls-enforcement flag.\nAll outbound communication must use TLS. TLS configuration is required for all services and endpoints heimdall communicates with. This enforcement can be disabled (not recommended) by starting Heimdall with the --insecure-skip-egress-tls-enforcement flag.\nIf Heimdall is used in proxy mode, communication with upstream services while proxying requests must use TLS. This enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-upstream-tls-enforcement flag.\nConfiguring the trusted_proxies property to allow insecure networks (0.0.0.0/0, 0/0, 0000:0000:0000:0000:0000:0000:0000:0000/0, and ::/0) is prohibited. See also HTTP Header Security Considerations. This enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-secure-trusted-proxies-enforcement flag.\nThe authentication stage of the default rule cannot start with an insecure authenticator (i.e., authenticators that allow all requests to pass through). This enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-secure-default-rule-enforcement flag.\nFor development purposes, all of the above settings can be disabled at once by starting heimdall with the --insecure flag.\nIf any of the above enforcement settings are disabled and an insecure configuration is used, warnings will be logged.\nHTTP Header Security Considerations If trusted_proxies property is configured (see also the corresponding configuration options) to let heimdall make use of different HTTP headers to build the URL for rule and HTTP method matching purposes, following logic apply:\nThe value for the used HTTP scheme is taken from the X-Forwarded-Proto header.\nThe value for the used HTTP host and port is taken from the X-Forwarded-Host header.\nThe value for the used HTTP path is taken from X-Forwarded-Uri header, which may also contain query parameters.\nThe value for the used HTTP method is taken from the X-Forwarded-Method header.\nIf the evaluation result for any of the above said steps is empty, the corresponding value is taken from the actual request to heimdall. E.g. if X-Forwarded-Method is set, the HTTP method used to communicate with heimdall is used for rule matching respectively evaluation purposes.\nThat means, if the client integrating with heimdall does not make use of the above said headers and does not drop them, a malicious actor could spoof them most probably leading to privileges escalation (depending on your rules). To avoid such situations, please adhere to the following practices:\nIf you can, try avoiding usage of trusted_proxies. Nothing can be spoofed then. However, you will lose the information about the used HTTP scheme, host and port and cannot rely on these in your rules.\nConfigure all headers and use those taking precedence. That is, always set X-Forwarded-Method, X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Uri.\nIf you cannot influence, which headers are set by your system, you’re integrating with heimdall, let it drop unused ones. E.g. If the proxy forwarding the request to heimdall by default sets only X-Forwarded-Proto and X-Forwarded-Host, let it drop the X-Forwarded-Method and X-Forwarded-Uri headers.\nThe API Gateways \u0026amp; Proxies Guides follow these practices, respectively highlight where caution is required. So, you can find examples there.\nObservability Information Logs, metrics and profiling information is very valuable for operating heimdall. These are however also very valuable for any adversary. For this reason, the corresponding services, exposing such information are by default, if enabled, listening only on the loopback (127.0.0.1) interface. If you have to configure them to listen to other interfaces, e.g. because you operate heimdall in a container, make sure, you don’t expose them publicly.\nTLS Trust Store As documented in Concepts section, the execution of heimdall’s pipeline typically includes communication to other systems. The endpoints of the corresponding systems should be TLS protected. This is however actually out of scope for heimdall. What is in scope, is the verification of the used TLS server certificate if TLS is used. This happens by making use of the operating system-wide trust store, containing the certificates of Root and Intermediate CAs (trust anchors) shipped with the OS. That means, you should\nensure this trust store contains the certificates of the Root CAs of your PKI hierarchy and\nensure the endpoints, heimdall communicates with over TLS, provide not only their own certificates, but also the intermediate certificates and cross certificates not included within the OS trust store\nBoth is required to enable heimdall building the certificate chain for TLS server certificate verification purpose. If heimdall fails doing so, the connection will be dropped.\nAs written above, heimdall makes use of the OS wide trust store to build the certificate chain. The most common installation directory on a Linux system for that trust store is the /etc/ssl/certs directory. In addition to the separate root and intermediate CA certificates, it also contains a ca-certificates.crt file, containing all installed certificates as well. This file is used by heimdall for the aforesaid purpose.\nheimdall container image is shipped without any certificates by intention to ensure you take care about the up-to-date status of the trust store. This way, if you use heimdall in a container, you have to mount the OS trust store into heimdall’s container to enable its usage.\nE.g.\ndocker run -t -p 4455:4455 \\ -v $PWD:/heimdall/conf \\ -v /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro \\ dadrus/heimdall:dev serve decision \\ -c /heimdall/conf/heimdall.yaml The verification of TLS server certificates is not the single configuration option. You should also ensure heimdall’s services, you’re using, are configured to be available via TLS as well. See TLS Configuration for all available options.\nSecurity Considerations In a typical production scenario, there is a need for proper key and certificate management. This is supported by heimdall in the following way:\nyou can and should configure not only the private key for signature creation purposes, but also the corresponding certificate chain. This way your upstream services are able not only to verify the signatures of the signed objects for cryptographic validity, but also perform verification of the revocation status of used certificates and also their time validity. All of that is crucial for secure communication.\nThe cryptographic material for the above said verification purposes is available via the JWKS endpoint for the upstream services.\nyou can configure multiple keys in heimdall’s key_store and specify the key_id of the key to use. The easiest way to let heimdall use the key id, you need, is to set X-Key-ID header in the PEM block of the corresponding private key (as also shown in the example above). Usage of key ids allows for seamless key rotation in setups which do not support or allow usage of secret management systems, respectively hot reloading of the corresponding updates by heimdall.\nSecret Management \u0026amp; Rotation When configuring heimdall, there are many places requiring secrets, like passwords, tokens, key material, etc. While you can directly configure these in heimdall’s config file, there is a huge chance for leaking them. Please reference the secrets in the config file via environment variables, or make use of external files where possible instead, and let the contents of these be managed by a secret management system.\nUsage of external files can even allow you to rotate the configured secrets without the need to restart heimdall if desired. Watching for secrets rotation is however disabled by default, but can be enabled by setting the secrets_reload_enabled property to true on the top level of heimdall’s configuration.\nAs of today secret reloading is only supported for key stores and Redis cache backend credentials. Verifying Heimdall Binaries and Container Images Heimdall binaries and container images are signed using Cosign and the keyless signing feature.\nPrerequisites Install Cosign\nContainer Image Signature Verification The signatures are stored in a repository named dadrus/heimdall-signatures. To verify the container image using Cosign, execute the following command:\nCOSIGN_REPOSITORY=dadrus/heimdall-signatures \\ cosign verify dadrus/heimdall:\u0026lt;tag\u0026gt; \\ --certificate-identity-regexp=https://github.com/dadrus/heimdall/.github/workflows/ci.yaml* \\ --certificate-oidc-issuer=https://token.actions.githubusercontent.com | jq If you pull heimdall images from ghcr.io, reference the ghcr.io registry while specifying the repository names. So dadrus/heimdall-signatures becomes ghcr.io/dadrus/heimdall-signatures and dadrus/heimdall:\u0026lt;tag\u0026gt; becomes ghcr.io/dadrus/heimdall:\u0026lt;tag\u0026gt;. In successful verification case, cosign will print similar output to the one shown below and exit with 0.\n[ { \u0026#34;critical\u0026#34;: { \u0026#34;identity\u0026#34;: { \u0026#34;docker-reference\u0026#34;: \u0026#34;index.docker.io/dadrus/heimdall\u0026#34; }, \u0026#34;image\u0026#34;: { \u0026#34;docker-manifest-digest\u0026#34;: \u0026#34;sha256:289b1a3eeeceeef08362a6fbcf4b95e726686d17998798e149c30b6974728eaf\u0026#34; }, \u0026#34;type\u0026#34;: \u0026#34;cosign container image signature\u0026#34; }, \u0026#34;optional\u0026#34;: { \u0026#34;1.3.6.1.4.1.57264.1.1\u0026#34;: \u0026#34;https://token.actions.githubusercontent.com\u0026#34;, \u0026#34;1.3.6.1.4.1.57264.1.2\u0026#34;: \u0026#34;push\u0026#34;, \u0026#34;1.3.6.1.4.1.57264.1.3\u0026#34;: \u0026#34;04379639dc5f3fbfc260e883ee4938a35076d63e\u0026#34;, \u0026#34;1.3.6.1.4.1.57264.1.4\u0026#34;: \u0026#34;CI\u0026#34;, \u0026#34;1.3.6.1.4.1.57264.1.5\u0026#34;: \u0026#34;dadrus/heimdall\u0026#34;, \u0026#34;1.3.6.1.4.1.57264.1.6\u0026#34;: \u0026#34;refs/heads/main\u0026#34;, \u0026#34;Bundle\u0026#34;: { \u0026#34;SignedEntryTimestamp\u0026#34;: \u0026#34;MEUCIFIvxs30zysroG6ItUNL+hfE3Cxn4GuiQe8d1u5N27OEAiEAqmzLrw80846U53nL/jtQ3U/2yx8Jqu8H75g6sihIcpg=\u0026#34;, \u0026#34;Payload\u0026#34;: { \u0026#34;body\u0026#34;: \u0026#34;eyJhcGlWZXJzaW9uIjoi...xTMHRMUW89In19fX0=\u0026#34;, \u0026#34;integratedTime\u0026#34;: 1692727396, \u0026#34;logIndex\u0026#34;: 32332529, \u0026#34;logID\u0026#34;: \u0026#34;c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d\u0026#34; } }, \u0026#34;Issuer\u0026#34;: \u0026#34;https://token.actions.githubusercontent.com\u0026#34;, \u0026#34;Subject\u0026#34;: \u0026#34;https://github.com/dadrus/heimdall/.github/workflows/ci.yaml@refs/heads/main\u0026#34;, \u0026#34;githubWorkflowName\u0026#34;: \u0026#34;CI\u0026#34;, \u0026#34;githubWorkflowRef\u0026#34;: \u0026#34;refs/heads/main\u0026#34;, \u0026#34;githubWorkflowRepository\u0026#34;: \u0026#34;dadrus/heimdall\u0026#34;, \u0026#34;githubWorkflowSha\u0026#34;: \u0026#34;04379639dc5f3fbfc260e883ee4938a35076d63e\u0026#34;, \u0026#34;githubWorkflowTrigger\u0026#34;: \u0026#34;push\u0026#34; } } ] For released images, the Subject value ends with @refs/tags/\u0026lt;release version\u0026gt;.\nRelease Binary Signature Verification The detached signatures, as well as certificates for all released archives are published together with the corresponding platform specific archive. The names of the signature files adhere to the \u0026lt;archive\u0026gt;-keyless.sig name pattern and the names of the certificate files adhere to the \u0026lt;archive\u0026gt;-keyless.pem name pattern, with \u0026lt;archive\u0026gt; being the archive for a platform specific build.\nTo verify the signature of the archive, hence its contents including the platform specific heimdall binary with Cosign execute the following command:\ncosign verify-blob /path/to/the/downloaded/\u0026lt;archive\u0026gt; \\ --certificate-identity-regexp=https://github.com/dadrus/heimdall/.github/workflows/ci.yaml* \\ --certificate-oidc-issuer=https://token.actions.githubusercontent.com \\ --signature /path/to/the/downloaded/\u0026lt;archive\u0026gt;-keyless.sig \\ --certificate /path/to/the/downloaded/\u0026lt;archive\u0026gt;--keyless.pem In successful verification case, cosign will print the following output and exit with 0.\nVerified OK Software Bill of Material (SBOM) Heimdall is shipped with an SBOM in CyclonDX (json) format.\nIf you use a released binary of heimdall, the corresponding file is part of the platform specific archive. That way, if you verify the signature of the archive (see above), you do also get evidence about the validity of the SBOM.\nIf you use a container image, the same SBOM is attached to the image as attestation signed with Cosign. These attestations are stored in the dadrus/heimdall-sbom repository. To verify the attestation and retrieve the SBOM execute the following command once Cosign is installed:\nCOSIGN_REPOSITORY=dadrus/heimdall-sbom \\ cosign verify-attestation dadrus/heimdall:\u0026lt;tag\u0026gt; \\ --certificate-identity-regexp=https://github.com/dadrus/heimdall/.github/workflows/ci.yaml* \\ --certificate-oidc-issuer=https://token.actions.githubusercontent.com \\ --type=cyclonedx If you pull heimdall images from ghcr.io, reference the ghcr.io registry while specifying the repository names. So dadrus/heimdall-sbom becomes ghcr.io/dadrus/heimdall-sbom and dadrus/heimdall:\u0026lt;tag\u0026gt; becomes ghcr.io/dadrus/heimdall:\u0026lt;tag\u0026gt;. In successful verification case, cosign will print similar output to the one shown below and exit with 0.\n{ \u0026#34;payloadType\u0026#34;: \u0026#34;application/vnd.in-toto+json\u0026#34;, \u0026#34;payload\u0026#34;: \u0026#34;eyJfdHlwZSI6Imh...LCJ2ZXJzaW9uIjoxfX0=\u0026#34;, \u0026#34;signatures\u0026#34;: [ { \u0026#34;keyid\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;sig\u0026#34;: \u0026#34;MEQCICGdo9hmIUrBRzVQ23VS...6ToNGa5YrommZNCQ==\u0026#34; } ] } Here, payload is the base64 encoded attestation value embedding the SBOM.\nAs one-liner, you can verify the signature and extract the SBOM as follows:\nCOSIGN_REPOSITORY=dadrus/heimdall-sbom \\ cosign verify-attestation dadrus/heimdall:\u0026lt;tag\u0026gt; \\ --certificate-identity-regexp=https://github.com/dadrus/heimdall/.github/workflows/ci.yaml* \\ --certificate-oidc-issuer=https://token.actions.githubusercontent.com \\ --type=cyclonedx | jq -r \u0026#34;.payload\u0026#34; | base64 -d | jq -r \u0026#34;.predicate\u0026#34; \u0026gt; heimdall.sbom.json The result will be the heimdall.sbom.json SBOM document, which you can use with any SCA or monitoring tool of your choice, e.g. Dependency Track.\n","description":"To operate heimdall in a secure way, you should configure heimdall accordingly. Following sections address the corresponding areas.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_defaults\"\u003eDefaults\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following configurations and behaviors are enforced by default:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eAll inbound communication must use TLS. TLS configuration is required for all services and endpoints exposed by heimdall. This enforcement can be disabled (not recommended) by starting Heimdall with the \u003ccode\u003e--insecure-skip-ingress-tls-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAll outbound communication must use TLS. TLS configuration is required for all services and endpoints heimdall communicates with. This enforcement can be disabled (not recommended) by starting Heimdall with the \u003ccode\u003e--insecure-skip-egress-tls-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf Heimdall is used in \u003ca href=\"/docs/concepts/operating_modes/#_proxy_mode\"\u003eproxy mode\u003c/a\u003e, communication with upstream services while proxying requests must use TLS. This enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-upstream-tls-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eConfiguring the \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003e\u003ccode\u003etrusted_proxies\u003c/code\u003e\u003c/a\u003e property to allow insecure networks (\u003ccode\u003e0.0.0.0/0\u003c/code\u003e, \u003ccode\u003e0/0\u003c/code\u003e, \u003ccode\u003e0000:0000:0000:0000:0000:0000:0000:0000/0\u003c/code\u003e, and \u003ccode\u003e::/0\u003c/code\u003e) is prohibited. See also \u003ca href=\"/docs/operations/security/#_http_header_security_considerations\"\u003eHTTP Header Security Considerations\u003c/a\u003e. This enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-secure-trusted-proxies-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe authentication stage of the \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e cannot start with an insecure authenticator (i.e., authenticators that allow all requests to pass through). This enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-secure-default-rule-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor development purposes, all of the above settings can be disabled at once by starting heimdall with the \u003ccode\u003e--insecure\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf any of the above enforcement settings are disabled and an insecure configuration is used, warnings will be logged.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_http_header_security_considerations\"\u003eHTTP Header Security Considerations\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf \u003ccode\u003etrusted_proxies\u003c/code\u003e property is configured (see also the corresponding \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003econfiguration options\u003c/a\u003e) to let heimdall make use of different HTTP headers to build the URL for rule and HTTP method matching purposes, following logic apply:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eThe value for the used HTTP scheme is taken from the \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe value for the used HTTP host and port is taken from the \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e header.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe value for the used HTTP path is taken from \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e header, which may also contain query parameters.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe value for the used HTTP method is taken from the \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e header.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the evaluation result for any of the above said steps is empty, the corresponding value is taken from the actual request to heimdall. E.g. if \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e is set, the HTTP method used to communicate with heimdall is used for rule matching respectively evaluation purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThat means, if the client integrating with heimdall does not make use of the above said headers and does not drop them, a malicious actor could spoof them most probably leading to privileges escalation (depending on your rules). To avoid such situations, please adhere to the following practices:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIf you can, try avoiding usage of \u003ccode\u003etrusted_proxies\u003c/code\u003e. Nothing can be spoofed then. However, you will lose the information about the used HTTP scheme, host and port and cannot rely on these in your rules.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eConfigure all headers and use those taking precedence. That is, always set \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf you cannot influence, which headers are set by your system, you’re integrating with heimdall, let it drop unused ones. E.g. If the proxy forwarding the request to heimdall by default sets only \u003ccode\u003eX-Forwarded-Proto\u003c/code\u003e and \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e, let it drop the \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e and \u003ccode\u003eX-Forwarded-Uri\u003c/code\u003e headers.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"/guides/proxies/\"\u003eAPI Gateways \u0026amp; Proxies Guides\u003c/a\u003e follow these practices, respectively highlight where caution is required. So, you can find examples there.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_observability_information\"\u003eObservability Information\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eLogs, metrics and profiling information is very valuable for operating heimdall. These are however also very valuable for any adversary. For this reason, the corresponding services, exposing such information are by default, if enabled, listening only on the loopback (\u003ccode\u003e127.0.0.1\u003c/code\u003e) interface. If you have to configure them to listen to other interfaces, e.g. because you operate heimdall in a container, make sure, you don’t expose them publicly.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_tls_trust_store\"\u003eTLS Trust Store\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs documented in \u003ca href=\"/docs/concepts/pipelines/\"\u003eConcepts\u003c/a\u003e section, the execution of heimdall’s pipeline typically includes communication to other systems. The endpoints of the corresponding systems should be TLS protected. This is however actually out of scope for heimdall. What is in scope, is the verification of the used TLS server certificate if TLS is used. This happens by making use of the operating system-wide trust store, containing the certificates of Root and Intermediate CAs (trust anchors) shipped with the OS. That means, you should\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eensure this trust store contains the certificates of the Root CAs of your PKI hierarchy and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eensure the endpoints, heimdall communicates with over TLS, provide not only their own certificates, but also the intermediate certificates and cross certificates not included within the OS trust store\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBoth is required to enable heimdall building the certificate chain for TLS server certificate verification purpose. If heimdall fails doing so, the connection will be dropped.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs written above, heimdall makes use of the OS wide trust store to build the certificate chain. The most common installation directory on a Linux system for that trust store is the \u003ccode\u003e/etc/ssl/certs\u003c/code\u003e directory. In addition to the separate root and intermediate CA certificates, it also contains a \u003ccode\u003eca-certificates.crt\u003c/code\u003e file, containing all installed certificates as well. This file is used by heimdall for the aforesaid purpose.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eheimdall container image is shipped without any certificates by intention to ensure you take care about the up-to-date status of the trust store. This way, if you use heimdall in a container, you have to mount the OS trust store into heimdall’s container to enable its usage.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003edocker run \u003cspan class=\"nt\"\u003e-t\u003c/span\u003e \u003cspan class=\"nt\"\u003e-p\u003c/span\u003e 4455:4455 \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-v\u003c/span\u003e \u003cspan class=\"nv\"\u003e$PWD\u003c/span\u003e:/heimdall/conf \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-v\u003c/span\u003e /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n dadrus/heimdall:dev serve decision \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e-c\u003c/span\u003e /heimdall/conf/heimdall.yaml\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe verification of TLS server certificates is not the single configuration option. You should also ensure heimdall’s services, you’re using, are configured to be available via TLS as well. See \u003ca href=\"/docs/configuration/types/#_tls\"\u003eTLS Configuration\u003c/a\u003e for all available options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_security_considerations\"\u003eSecurity Considerations\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn a typical production scenario, there is a need for proper key and certificate management. This is supported by heimdall in the following way:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eyou can and should configure not only the private key for signature creation purposes, but also the corresponding certificate chain. This way your upstream services are able not only to verify the signatures of the signed objects for cryptographic validity, but also perform verification of the revocation status of used certificates and also their time validity. All of that is crucial for secure communication.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe cryptographic material for the above said verification purposes is available via the \u003ca href=\"/openapi/#tag/Well-Known/operation/well_known_jwks\"\u003eJWKS endpoint\u003c/a\u003e for the upstream services.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eyou can configure multiple keys in heimdall’s \u003ccode\u003ekey_store\u003c/code\u003e and specify the \u003ccode\u003ekey_id\u003c/code\u003e of the key to use. The easiest way to let heimdall use the key id, you need, is to set \u003ccode\u003eX-Key-ID\u003c/code\u003e header in the PEM block of the corresponding private key (as also shown in the example above). Usage of key ids allows for seamless key rotation in setups which do not support or allow usage of secret management systems, respectively hot reloading of the corresponding updates by heimdall.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_secret_management_rotation\"\u003eSecret Management \u0026amp; Rotation\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhen configuring heimdall, there are many places requiring secrets, like passwords, tokens, key material, etc. While you can directly configure these in heimdall’s config file, there is a huge chance for leaking them. Please reference the secrets in the config file via \u003ca href=\"/docs/operations/configuration/#_configuration_file\"\u003eenvironment variables\u003c/a\u003e, or make use of external files where possible instead, and let the contents of these be managed by a secret management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUsage of external files can even allow you to rotate the configured secrets without the need to restart heimdall if desired. Watching for secrets rotation is however disabled by default, but can be enabled by setting the \u003ccode\u003esecrets_reload_enabled\u003c/code\u003e property to \u003ccode\u003etrue\u003c/code\u003e on the top level of heimdall’s configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAs of today secret reloading is only supported for \u003ca href=\"/docs/configuration/types/#_key_store\"\u003ekey stores\u003c/a\u003e and \u003ca href=\"/docs/operations/cache/#_common_settings\"\u003eRedis cache backend credentials\u003c/a\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_verifying_heimdall_binaries_and_container_images\"\u003eVerifying Heimdall Binaries and Container Images\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall binaries and container images are signed using \u003ca href=\"https://docs.sigstore.dev/docs/signing/quickstart/\"\u003eCosign\u003c/a\u003e and the \u003ca href=\"https://docs.sigstore.dev/docs/signing/overview/\"\u003ekeyless signing feature\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_prerequisites\"\u003ePrerequisites\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eInstall \u003ca href=\"https://docs.sigstore.dev/docs/system_config/installation/\"\u003eCosign\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_container_image_signature_verification\"\u003eContainer Image Signature Verification\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe signatures are stored in a repository named \u003ccode\u003edadrus/heimdall-signatures\u003c/code\u003e. To verify the container image using Cosign, execute the following command:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eCOSIGN_REPOSITORY\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003edadrus/heimdall-signatures \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\ncosign verify dadrus/heimdall:\u0026lt;tag\u0026gt; \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-identity-regexp\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://github.com/dadrus/heimdall/.github/workflows/ci.yaml\u003cspan class=\"k\"\u003e*\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-oidc-issuer\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://token.actions.githubusercontent.com | jq\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you pull heimdall images from ghcr.io, reference the \u003ccode\u003eghcr.io\u003c/code\u003e registry while specifying the repository names. So \u003ccode\u003edadrus/heimdall-signatures\u003c/code\u003e becomes \u003ccode\u003eghcr.io/dadrus/heimdall-signatures\u003c/code\u003e and \u003ccode\u003edadrus/heimdall:\u0026lt;tag\u0026gt;\u003c/code\u003e becomes \u003ccode\u003eghcr.io/dadrus/heimdall:\u0026lt;tag\u0026gt;\u003c/code\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn successful verification case, cosign will print similar output to the one shown below and exit with \u003ccode\u003e0\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;critical\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;identity\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;docker-reference\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;index.docker.io/dadrus/heimdall\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e},\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;image\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;docker-manifest-digest\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;sha256:289b1a3eeeceeef08362a6fbcf4b95e726686d17998798e149c30b6974728eaf\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e},\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;type\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;cosign container image signature\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e},\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;optional\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.1\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://token.actions.githubusercontent.com\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.2\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;push\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.3\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;04379639dc5f3fbfc260e883ee4938a35076d63e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.4\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;CI\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.5\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;dadrus/heimdall\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;1.3.6.1.4.1.57264.1.6\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;refs/heads/main\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;Bundle\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;SignedEntryTimestamp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;MEUCIFIvxs30zysroG6ItUNL+hfE3Cxn4GuiQe8d1u5N27OEAiEAqmzLrw80846U53nL/jtQ3U/2yx8Jqu8H75g6sihIcpg=\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;Payload\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;body\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;eyJhcGlWZXJzaW9uIjoi...xTMHRMUW89In19fX0=\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;integratedTime\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1692727396\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;logIndex\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e32332529\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;logID\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e},\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;Issuer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://token.actions.githubusercontent.com\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;Subject\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://github.com/dadrus/heimdall/.github/workflows/ci.yaml@refs/heads/main\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;githubWorkflowName\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;CI\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;githubWorkflowRef\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;refs/heads/main\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;githubWorkflowRepository\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;dadrus/heimdall\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;githubWorkflowSha\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;04379639dc5f3fbfc260e883ee4938a35076d63e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;githubWorkflowTrigger\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;push\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor released images, the \u003ccode\u003eSubject\u003c/code\u003e value ends with \u003ccode\u003e@refs/tags/\u0026lt;release version\u0026gt;\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_release_binary_signature_verification\"\u003eRelease Binary Signature Verification\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe detached signatures, as well as certificates for all released archives are published together with the corresponding platform specific archive. The names of the signature files adhere to the \u003ccode\u003e\u0026lt;archive\u0026gt;-keyless.sig\u003c/code\u003e name pattern and the names of the certificate files adhere to the \u003ccode\u003e\u0026lt;archive\u0026gt;-keyless.pem\u003c/code\u003e name pattern, with \u003ccode\u003e\u0026lt;archive\u0026gt;\u003c/code\u003e being the archive for a platform specific build.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo verify the signature of the archive, hence its contents including the platform specific heimdall binary with Cosign execute the following command:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003ecosign verify-blob /path/to/the/downloaded/\u0026lt;archive\u0026gt; \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-identity-regexp\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://github.com/dadrus/heimdall/.github/workflows/ci.yaml\u003cspan class=\"k\"\u003e*\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-oidc-issuer\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://token.actions.githubusercontent.com \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--signature\u003c/span\u003e /path/to/the/downloaded/\u0026lt;archive\u0026gt;-keyless.sig \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate\u003c/span\u003e /path/to/the/downloaded/\u0026lt;archive\u0026gt;--keyless.pem\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn successful verification case, cosign will print the following output and exit with \u003ccode\u003e0\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eVerified OK\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_software_bill_of_material_sbom\"\u003eSoftware Bill of Material (SBOM)\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall is shipped with an SBOM in \u003ca href=\"https://cyclonedx.org/\"\u003eCyclonDX\u003c/a\u003e (json) format.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you use a released binary of heimdall, the corresponding file is part of the platform specific archive. That way, if you verify the signature of the archive (see above), you do also get evidence about the validity of the SBOM.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you use a container image, the same SBOM is attached to the image as attestation signed with Cosign. These attestations are stored in the \u003ccode\u003edadrus/heimdall-sbom\u003c/code\u003e repository. To verify the attestation and retrieve the SBOM execute the following command once Cosign is installed:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eCOSIGN_REPOSITORY\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003edadrus/heimdall-sbom \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\ncosign verify-attestation dadrus/heimdall:\u0026lt;tag\u0026gt; \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-identity-regexp\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://github.com/dadrus/heimdall/.github/workflows/ci.yaml\u003cspan class=\"k\"\u003e*\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-oidc-issuer\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://token.actions.githubusercontent.com \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--type\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ecyclonedx\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you pull heimdall images from ghcr.io, reference the \u003ccode\u003eghcr.io\u003c/code\u003e registry while specifying the repository names. So \u003ccode\u003edadrus/heimdall-sbom\u003c/code\u003e becomes \u003ccode\u003eghcr.io/dadrus/heimdall-sbom\u003c/code\u003e and \u003ccode\u003edadrus/heimdall:\u0026lt;tag\u0026gt;\u003c/code\u003e becomes \u003ccode\u003eghcr.io/dadrus/heimdall:\u0026lt;tag\u0026gt;\u003c/code\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn successful verification case, cosign will print similar output to the one shown below and exit with \u003ccode\u003e0\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;payloadType\u0026#34;\u003c/span\u003e: \u003cspan class=\"s2\"\u003e\u0026#34;application/vnd.in-toto+json\u0026#34;\u003c/span\u003e,\n \u003cspan class=\"s2\"\u003e\u0026#34;payload\u0026#34;\u003c/span\u003e: \u003cspan class=\"s2\"\u003e\u0026#34;eyJfdHlwZSI6Imh...LCJ2ZXJzaW9uIjoxfX0=\u0026#34;\u003c/span\u003e,\n \u003cspan class=\"s2\"\u003e\u0026#34;signatures\u0026#34;\u003c/span\u003e: \u003cspan class=\"o\"\u003e[\u003c/span\u003e\n \u003cspan class=\"o\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;keyid\u0026#34;\u003c/span\u003e: \u003cspan class=\"s2\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e,\n \u003cspan class=\"s2\"\u003e\u0026#34;sig\u0026#34;\u003c/span\u003e: \u003cspan class=\"s2\"\u003e\u0026#34;MEQCICGdo9hmIUrBRzVQ23VS...6ToNGa5YrommZNCQ==\u0026#34;\u003c/span\u003e\n \u003cspan class=\"o\"\u003e}\u003c/span\u003e\n \u003cspan class=\"o\"\u003e]\u003c/span\u003e\n\u003cspan class=\"o\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, \u003ccode\u003epayload\u003c/code\u003e is the base64 encoded attestation value embedding the SBOM.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs one-liner, you can verify the signature and extract the SBOM as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003eCOSIGN_REPOSITORY\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003edadrus/heimdall-sbom \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\ncosign verify-attestation dadrus/heimdall:\u0026lt;tag\u0026gt; \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-identity-regexp\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://github.com/dadrus/heimdall/.github/workflows/ci.yaml\u003cspan class=\"k\"\u003e*\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--certificate-oidc-issuer\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ehttps://token.actions.githubusercontent.com \u003cspan class=\"se\"\u003e\\\u003c/span\u003e\n \u003cspan class=\"nt\"\u003e--type\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003ecyclonedx | jq \u003cspan class=\"nt\"\u003e-r\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;.payload\u0026#34;\u003c/span\u003e | \u003cspan class=\"nb\"\u003ebase64\u003c/span\u003e \u003cspan class=\"nt\"\u003e-d\u003c/span\u003e | jq \u003cspan class=\"nt\"\u003e-r\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;.predicate\u0026#34;\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e heimdall.sbom.json\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe result will be the \u003ccode\u003eheimdall.sbom.json\u003c/code\u003e SBOM document, which you can use with any SCA or monitoring tool of your choice, e.g. \u003ca href=\"https://dependencytrack.org/\"\u003eDependency Track\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Operations"],"tags":null,"title":"Security","url":"/docs/operations/security/"},{"categories":null,"content":" To make use of this service you have to start heimdall with either heimdall serve proxy or heimdall serve decision. By default, heimdall listens on 0.0.0.0:4455 endpoint for incoming requests and also configures useful defaults. You can, and should however adjust the configuration for your needs.\nConfiguration The configuration of this service can be adjusted in the serve property, which lives on the top level of heimdall’s configuration and supports the following properties.\nhost: string (optional)\nBy making use of this property, you can specify the TCP/IP address on which heimdall should listen for connections from client applications. The entry 0.0.0.0 allows listening for all IPv4 addresses. 0.0.0.0 is also the default setting.\nport: integer (optional)\nBy making use of this property, you can specify the TCP port that heimdall should listen on. Defaults to 4455.\ntimeout: Timeout (optional)\nBy using this property, you can override the default timeouts used by heimdall. Following properties are supported:\nidle: Duration (optional)\nThe maximum amount of time to wait for the next request when keep-alive is enabled. If set to 0, the value of the read timeout is used. Defaults to 2 minutes. If heimdall is operated in proxy mode, this value is also used for the maximum amount of time an idle (keep-alive) connection to the upstream will remain idle before closing itself.\nread: Duration (optional)\nThe absolute amount of time allowed to read the entire request, including body. Defaults to 5 seconds. If heimdall is operated in proxy mode, the read timeout is also used while waiting for the responses from the upstream service. Here it specifies the amount of time to wait for a server’s response headers after fully writing the request (including its body, if any). Upon successful upgrade responses from the upstream service, this timeout is disabled, allowing e.g. for WebSockets proxying. Setting this property to 0s will disable the timeout.\nSetting this timeout to 0 will make heimdall vulnerable to Slowloris attacks). write: Duration (optional)\nThe maximum duration before timing out writes of the response. Defaults to 10 seconds. Setting this property to 0s will disable the timeout. Compared to the read timeout, the write timeout is not absolute and resets each time data is written to the output stream if heimdall is operated in proxy mode. This allows Server-Sent-Events and other unidirectional communication without the need to extend the timeout. As with the read timeout, this timeout is disabled upon successful upgrade responses from the upstream service, allowing e.g. for WebSockets proxying.\nbuffer_limit: BufferLimit (optional)\nBuffer limits for inbound requests and outbound responses.\nread: ByteSize (optional)\nThe maximum size for the read buffer allowed to read the full request including body. Defaults to 4KB.\nwrite: ByteSize (optional)\nThe maximum size for the write buffer of the response. Defaults to 4KB.\nconnections_limit: ConnectionsLimit (optional)\nIf heimdall is operated in proxy mode, this property configures allowed connections limit per upstream service (ignored in decision mode). Following limits can be configured:\nmax_per_host: integer (optional)\nLimits the total number of connections per host, including connections in the dialing, active, and idle states. On limit violation, dials will block. Defaults to 0, which means there is no limit.\nmax_idle: integer (optional)\nControls the maximum number of idle (keep-alive) connections across all hosts. 0 means no limit. Defaults to 100.\nmax_idle_per_host: integer (optional)\nControls the maximum number of idle (keep-alive) connections per host. Defaults to 100. Cannot exceed the value of max_idle.\ncors: CORS (optional)\nCORS (Cross-Origin Resource Sharing) headers can be added and configured by making use of this option. This functionality allows for advanced security features to quickly be set. If CORS headers are set, then heimdall does not pass preflight requests neither to its pipeline, nor to the upstream service. Instead, the response will be generated and sent back to the client directly.\ntls: TLS (optional)\nTLS-related configuration to ensure secure communication.\nAlthough this property is optional, heimdall enforces its usage by default. This enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-ingress-tls-enforcement flag. trusted_proxies: string array (optional)\nheimdall can process X-Forwarded-* headers, such as X-Forwarded-For, X-Forwarded-Method, etc., as well as the Forwarded header sent by its clients. Additionally, heimdall can forward some of these headers (X-Forwarded-For and Forwarded) to the configured upstream services. However, since these headers can easily be spoofed, they are only used when the request originates from a trusted source. This is typically the case when heimdall operates behind another proxy. For example, while the Host HTTP header is usually used to determine the client’s requested host, when heimdall is behind a proxy, the actual host of the ultimate client may be stored in an X-Forwarded-Host header, which, however, can also be spoofed.\nDepending on your setup, you may need to rely on these headers. In such cases, you must configure the trusted_proxies option and specify the IP addresses or IP ranges (in CIDR notation) of the proxies in front of heimdall. If this option is not configured, heimdall will reject these headers from all clients to prevent spoofing, as improper use could lead to privilege escalation.\nBe sure to review the security implications before enabling this property. heimdall does not allow configuring this property to accept these headers from any sources. Specifically, the networks 0.0.0.0/0, 0/0, 0000:0000:0000:0000:0000:0000:0000:0000/0, and ::/0 are disallowed by default. This enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-secure-trusted-proxies-enforcement flag if necessary. respond: Respond (optional)\nBy making use of this property, you can instruct heimdall to preserve error information and provide it in the response body to the caller, as well as to use HTTP status codes deviating from those heimdall would usually use.\nThis mapping is only applicable if the HTTP status code is set by heimdall and not by the upstream service in the response to the proxied request. For that reason, you cannot configure the mapping for the accepted response (it will be ignored). Example 1. Complex proxy service configuration. serve: host: 172.17.0.2 tls: key_store: path: /path/to/keystore.pem password: VerySecure! timeout: read: 1s write: 2s idle: 30s connections_limit: max_per_host: 20 max_idle: 100 max_idle_per_host: 10 buffer_limit: read: 4KB write: 10KB trusted_proxies: - 192.168.1.0/24 cors: allowed_origins: - example.org allowed_methods: - HEAD - PATCH allow_credentials: true max_age: 10s respond: verbose: true with: authentication_error: code: 404 authorization_error: code: 404 ","description":"This is heimdall's main service responsible for driving the actual access control decision process.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo make use of this service you have to start heimdall with either \u003ccode\u003eheimdall serve proxy\u003c/code\u003e or \u003ccode\u003eheimdall serve decision\u003c/code\u003e. By default, heimdall listens on \u003ccode\u003e0.0.0.0:4455\u003c/code\u003e endpoint for incoming requests and also configures useful defaults. You can, and should however adjust the configuration for your needs.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration\"\u003eConfiguration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this service can be adjusted in the \u003ccode\u003eserve\u003c/code\u003e property, which lives on the top level of heimdall’s configuration and supports the following properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehost\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can specify the TCP/IP address on which heimdall should listen for connections from client applications. The entry \u003ccode\u003e0.0.0.0\u003c/code\u003e allows listening for all IPv4 addresses. \u003ccode\u003e0.0.0.0\u003c/code\u003e is also the default setting.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eport\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can specify the TCP port that heimdall should listen on. Defaults to \u003ccode\u003e4455\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etimeout\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eTimeout\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy using this property, you can override the default timeouts used by heimdall. Following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eidle\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum amount of time to wait for the next request when keep-alive is enabled. If set to 0, the value of the \u003ccode\u003eread\u003c/code\u003e timeout is used. Defaults to 2 minutes. If heimdall is operated in proxy mode, this value is also used for the maximum amount of time an idle (keep-alive) connection to the upstream will remain idle before closing itself.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eread\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe absolute amount of time allowed to read the entire request, including body. Defaults to 5 seconds. If heimdall is operated in proxy mode, the \u003ccode\u003eread\u003c/code\u003e timeout is also used while waiting for the responses from the upstream service. Here it specifies the amount of time to wait for a server’s response headers after fully writing the request (including its body, if any). Upon successful upgrade responses from the upstream service, this timeout is disabled, allowing e.g. for WebSockets proxying. Setting this property to 0s will disable the timeout.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nSetting this timeout to 0 will make heimdall vulnerable to \u003ca href=\"https://en.wikipedia.org/wiki/Slowloris_(computer_security\"\u003eSlowloris attacks\u003c/a\u003e).\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum duration before timing out writes of the response. Defaults to 10 seconds. Setting this property to 0s will disable the timeout. Compared to the \u003ccode\u003eread\u003c/code\u003e timeout, the \u003ccode\u003ewrite\u003c/code\u003e timeout is not absolute and resets each time data is written to the output stream if heimdall is operated in proxy mode. This allows Server-Sent-Events and other unidirectional communication without the need to extend the timeout. As with the \u003ccode\u003eread\u003c/code\u003e timeout, this timeout is disabled upon successful upgrade responses from the upstream service, allowing e.g. for WebSockets proxying.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebuffer_limit\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eBufferLimit\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBuffer limits for inbound requests and outbound responses.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eread\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size for the read buffer allowed to read the full request including body. Defaults to 4KB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size for the write buffer of the response. Defaults to 4KB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003econnections_limit\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eConnectionsLimit\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf heimdall is operated in proxy mode, this property configures allowed connections limit per upstream service (ignored in decision mode). Following limits can be configured:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_per_host\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eLimits the total number of connections per host, including connections in the dialing, active, and idle states. On limit violation, dials will block. Defaults to 0, which means there is no limit.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_idle\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eControls the maximum number of idle (keep-alive) connections across all hosts. 0 means no limit. Defaults to 100.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_idle_per_host\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eControls the maximum number of idle (keep-alive) connections per host. Defaults to 100. Cannot exceed the value of \u003ccode\u003emax_idle\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecors\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_cors\"\u003eCORS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS\"\u003eCORS\u003c/a\u003e (Cross-Origin Resource Sharing) headers can be added and configured by making use of this option. This functionality allows for advanced security features to quickly be set. If CORS headers are set, then heimdall does not pass preflight requests neither to its pipeline, nor to the upstream service. Instead, the response will be generated and sent back to the client directly.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etls\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_tls\"\u003eTLS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTLS-related configuration to ensure secure communication.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAlthough this property is optional, heimdall enforces its usage by default. This enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-ingress-tls-enforcement\u003c/code\u003e flag.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_trusted_proxies\" class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etrusted_proxies\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eheimdall can process \u003ccode\u003eX-Forwarded-*\u003c/code\u003e headers, such as \u003ccode\u003eX-Forwarded-For\u003c/code\u003e, \u003ccode\u003eX-Forwarded-Method\u003c/code\u003e, etc., as well as the \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded\"\u003e\u003ccode\u003eForwarded\u003c/code\u003e\u003c/a\u003e header sent by its clients. Additionally, heimdall can forward some of these headers (\u003ccode\u003eX-Forwarded-For\u003c/code\u003e and \u003ccode\u003eForwarded\u003c/code\u003e) to the configured upstream services. However, since these headers can easily be spoofed, they are only used when the request originates from a trusted source. This is typically the case when heimdall operates behind another proxy. For example, while the \u003ccode\u003eHost\u003c/code\u003e HTTP header is usually used to determine the client’s requested host, when heimdall is behind a proxy, the actual host of the ultimate client may be stored in an \u003ccode\u003eX-Forwarded-Host\u003c/code\u003e header, which, however, can also be spoofed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDepending on your setup, you may need to rely on these headers. In such cases, you must configure the \u003ccode\u003etrusted_proxies\u003c/code\u003e option and specify the IP addresses or IP ranges (in CIDR notation) of the proxies in front of heimdall. If this option is not configured, heimdall will reject these headers from all clients to prevent spoofing, as improper use could lead to privilege escalation.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nBe sure to review the \u003ca href=\"/docs/operations/security/#_http_header_security_considerations\"\u003esecurity implications\u003c/a\u003e before enabling this property.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nheimdall does not allow configuring this property to accept these headers from any sources. Specifically, the networks \u003ccode\u003e0.0.0.0/0\u003c/code\u003e, \u003ccode\u003e0/0\u003c/code\u003e, \u003ccode\u003e0000:0000:0000:0000:0000:0000:0000:0000/0\u003c/code\u003e, and \u003ccode\u003e::/0\u003c/code\u003e are disallowed by default. This enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-secure-trusted-proxies-enforcement\u003c/code\u003e flag if necessary.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003erespond\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_respond\"\u003eRespond\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can instruct heimdall to preserve error information and provide it in the response body to the caller, as well as to use HTTP status codes deviating from those heimdall would usually use.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThis mapping is only applicable if the HTTP status code is set by heimdall and not by the upstream service in the response to the proxied request. For that reason, you cannot configure the mapping for the \u003ccode\u003eaccepted\u003c/code\u003e response (it will be ignored).\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Complex proxy service configuration.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eserve\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e172.17.0.2\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecure!\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e30s\u003c/span\u003e\n \u003cspan class=\"na\"\u003econnections_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_per_host\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e20\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_idle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e100\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_idle_per_host\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e10\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuffer_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e4KB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10KB\u003c/span\u003e\n \u003cspan class=\"na\"\u003etrusted_proxies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e192.168.1.0/24\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecors\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_origins\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eexample.org\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_methods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eHEAD\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePATCH\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_credentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_age\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\n \u003cspan class=\"na\"\u003erespond\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003everbose\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewith\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e404\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e404\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Services"],"tags":null,"title":"Main Service","url":"/docs/services/main/"},{"categories":null,"content":" By default, heimdall listens on 0.0.0.0:4457 for incoming requests and applies useful default timeouts and buffer limits. No additional options are configured by default, but you can adjust them as needed.\nThis service exposes the health and JWKS endpoints.\nConfiguration The configuration of the management endpoint is defined under the management property. It supports the following properties.\nhost: string (optional)\nUse this property to specify the TCP/IP address on which heimdall should listen for incoming connections. E.g. the entry 0.0.0.0 allows listening on all network interfaces for IPv4 and is the default setting.\nport: integer (optional)\nUse this property to specify the TCP port Heimdall should listen on. Defaults to 4457.\ntimeout: Timeout (optional)\nUse this property to override heimdall’s default timeouts. The following options are available:\nidle: Duration (optional)\nThe maximum time to wait for the next request when keep-alive is enabled. If set to 0s, the read timeout value is used. Defaults to 2 minutes.\nread: Duration (optional)\nThe maximum time allowed to read the entire request, including the body. Defaults to 5 seconds. Setting this property to 0s disables the timeout.\nwrite: Duration (optional)\nThe maximum duration before timing out response writes. Defaults to 10 seconds. Setting this property to 0s disables the timeout.\nbuffer_limit: BufferLimit (optional)\nDefines buffer limits for inbound requests and outbound responses. The following options are available:\nread: ByteSize (optional)\nThe maximum size of the read buffer for handling the full request, including the body. Defaults to 4KB.\nwrite: ByteSize (optional)\nThe maximum size of the write buffer for responses. Defaults to 4KB.\ncors: CORS (optional)\nCORS (Cross-Origin Resource Sharing) headers can be configured using this option. This allows for fine-grained security settings.\ntls: TLS (optional)\nTLS-related configuration to ensure secure communication.\nAlthough this property is optional, heimdall enforces its usage by default. This enforcement can be disabled (not recommended) by starting Heimdall with the --insecure-skip-ingress-tls-enforcement flag. Example 1. Complex management service configuration management: host: 127.0.0.1 tls: key_store: path: /path/to/keystore.pem password: VerySecure! timeout: read: 1s write: 2s idle: 30s buffer_limit: read: 4KB write: 10KB ","description":"When heimdall is started, the management service is always exposed and offers endpoints for health monitoring and retrieving keys and certificates used by Heimdall for JWT creation.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy default, heimdall listens on \u003ccode\u003e0.0.0.0:4457\u003c/code\u003e for incoming requests and applies useful default timeouts and buffer limits. No additional options are configured by default, but you can adjust them as needed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis service exposes the health and JWKS endpoints.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration\"\u003eConfiguration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of the management endpoint is defined under the \u003ccode\u003emanagement\u003c/code\u003e property. It supports the following properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehost\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUse this property to specify the TCP/IP address on which heimdall should listen for incoming connections. E.g. the entry \u003ccode\u003e0.0.0.0\u003c/code\u003e allows listening on all network interfaces for IPv4 and is the default setting.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eport\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003einteger\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUse this property to specify the TCP port Heimdall should listen on. Defaults to \u003ccode\u003e4457\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etimeout\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eTimeout\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUse this property to override heimdall’s default timeouts. The following options are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eidle\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum time to wait for the next request when keep-alive is enabled. If set to \u003ccode\u003e0s\u003c/code\u003e, the \u003ccode\u003eread\u003c/code\u003e timeout value is used. Defaults to 2 minutes.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eread\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum time allowed to read the entire request, including the body. Defaults to 5 seconds. Setting this property to \u003ccode\u003e0s\u003c/code\u003e disables the timeout.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum duration before timing out response writes. Defaults to 10 seconds. Setting this property to \u003ccode\u003e0s\u003c/code\u003e disables the timeout.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebuffer_limit\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eBufferLimit\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines buffer limits for inbound requests and outbound responses. The following options are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eread\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size of the read buffer for handling the full request, including the body. Defaults to 4KB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_bytesize\"\u003eByteSize\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe maximum size of the write buffer for responses. Defaults to 4KB.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecors\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_cors\"\u003eCORS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS\"\u003eCORS\u003c/a\u003e (Cross-Origin Resource Sharing) headers can be configured using this option. This allows for fine-grained security settings.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etls\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_tls\"\u003eTLS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTLS-related configuration to ensure secure communication.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAlthough this property is optional, heimdall enforces its usage by default. This enforcement can be disabled (not recommended) by starting Heimdall with the \u003ccode\u003e--insecure-skip-ingress-tls-enforcement\u003c/code\u003e flag.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Complex management service configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emanagement\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecure!\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e30s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuffer_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e4KB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10KB\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Services"],"tags":null,"title":"Management Service","url":"/docs/services/management/"},{"categories":null,"content":" As described in Concepts section, mechanisms must be defined and configured before these can be used in rules. That is happening in the so-called mechanisms catalogue. On start up heimdall instantiates all defined and configured mechanisms and makes these available for usage in rules.\nCatalogue Configuration The corresponding mechanisms catalogue resides under the mechanisms property of heimdall static configuration and is organized based on mechanism categories as also shown in the snippet below.\nmechanisms: authenticators: \u0026lt;list of authenticator definitions\u0026gt; authorizers: \u0026lt;list of authorizer definitions\u0026gt; contextualizers: \u0026lt;list of contextualizer definitions\u0026gt; finalizers: \u0026lt;list of finalizer definitions\u0026gt; error_handlers: \u0026lt;list of error handler definitions\u0026gt; General Mechanism Configuration Each mechanism definition entry in the catalogue contains the following properties:\nid - A mandatory unique identifier of the mechanism. Identifiers are used to reference the required mechanism within a rule, respectively its pipelines. You can choose whatever identifier, you want. It is just a name. It must however be unique across all defined mechanisms of a particular mechanism category (like authenticator, authorizer, etc.).\ntype - The mandatory specific type of the mechanism in the given category.\nconfig - The mechanism’s specific configuration if required by the type.\nEvery mechanism type can be configured as many times as needed. However, for those, which don’t have a configuration, it doesn’t really make sense, as all of them would behave the same way.\nFor example, your authenticator definitions could look like this:\nmechanisms: authenticators: - id: anon1 type: anonymous - id: anon2 type: anonymous - id: anon3 type: anonymous config: subject: anon - id: anon4 type: anonymous config: subject: bla The above snippet configures four different instances of the anonymous authenticator mechanism, with anon1 and anon2 being configured identically (as no configuration is provided), and anon3 and anon4 being different in their configuration. Since the first two mentioned behave the same way (both will set the Subject ID to anonymous), there is actually no need to define two instances of them.\nExample Here is an example which defines a mechanism catalogue using some of the available types:\nmechanisms: authenticators: - id: anon_authn type: anonymous - id: opaque_auth_token_authn type: oauth2_introspection config: introspection_endpoint: url: https://hydra:4445/oauth2/introspect assertions: issuers: - https://127.0.0.1:4444/ authorizers: - id: deny_all_authz type: deny - id: local_authz type: cel config: expressions: - expression: \u0026#34;manager\u0026#34; in Subject.Attributes.groups message: user is not in the expected group contextualizers: - id: group_manager type: generic config: endpoint: url: https://group-manager.local/groups method: GET forward_headers: - Authorization cache_ttl: 1m finalizers: - id: jwt_finalizer type: jwt config: signer: key_store: path: /etc/heimdall/signer.pem ttl: 5m claims: | { {{ $user_name := .Subject.Attributes.identity.user_name -}} \u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.identity.email }}, \u0026#34;email_verified\u0026#34;: {{ .Subject.Attributes.identity.email_verified }}, {{ if $user_name -}} \u0026#34;name\u0026#34;: {{ quote $user_name }} {{ else -}} \u0026#34;name\u0026#34;: {{ quote $email }} {{ end -}} } error_handlers: - id: default type: default - id: authenticate_with_kratos type: redirect config: to: https://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }} ","description":"Defines and configures those mechanisms, which should be available for usage in rules.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs described in \u003ca href=\"/docs/concepts/mechanisms/\"\u003eConcepts\u003c/a\u003e section, mechanisms must be defined and configured before these can be used in rules. That is happening in the so-called mechanisms catalogue. On start up heimdall instantiates all defined and configured mechanisms and makes these available for usage in rules.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_catalogue_configuration\"\u003eCatalogue Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe corresponding mechanisms catalogue resides under the \u003ccode\u003emechanisms\u003c/code\u003e property of heimdall static configuration and is organized based on mechanism categories as also shown in the snippet below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026lt;list of authenticator definitions\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026lt;list of authorizer definitions\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtextualizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026lt;list of contextualizer definitions\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026lt;list of finalizer definitions\u0026gt;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eerror_handlers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026lt;list of error handler definitions\u0026gt;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_general_mechanism_configuration\"\u003eGeneral Mechanism Configuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach mechanism definition entry in the catalogue contains the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eid\u003c/code\u003e - A mandatory unique identifier of the mechanism. Identifiers are used to reference the required mechanism within a rule, respectively its pipelines. You can choose whatever identifier, you want. It is just a name. It must however be unique across all defined mechanisms of a particular mechanism category (like authenticator, authorizer, etc.).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e - The mandatory specific type of the mechanism in the given category.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003econfig\u003c/code\u003e - The mechanism’s specific configuration if required by the type.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEvery mechanism type can be configured as many times as needed. However, for those, which don’t have a configuration, it doesn’t really make sense, as all of them would behave the same way.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFor example, your authenticator definitions could look like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon1\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon2\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon3\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon4\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe above snippet configures four different instances of the anonymous authenticator mechanism, with \u003ccode\u003eanon1\u003c/code\u003e and \u003ccode\u003eanon2\u003c/code\u003e being configured identically (as no configuration is provided), and \u003ccode\u003eanon3\u003c/code\u003e and \u003ccode\u003eanon4\u003c/code\u003e being different in their configuration. Since the first two mentioned behave the same way (both will set the Subject ID to \u003ccode\u003eanonymous\u003c/code\u003e), there is actually no need to define two instances of them.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_example\"\u003eExample\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere is an example which defines a mechanism catalogue using some of the available types:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon_authn\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopaque_auth_token_authn\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_introspection\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eintrospection_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://hydra:4445/oauth2/introspect\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4444/\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003elocal_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003emanager\u0026#34;\u003c/span\u003e \u003cspan class=\"s\"\u003ein Subject.Attributes.groups\u003c/span\u003e\n \u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003euser is not in the expected group\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtextualizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egroup_manager\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://group-manager.local/groups\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1m\u003c/span\u003e\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_finalizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/etc/heimdall/signer.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclaims\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ $user_name := .Subject.Attributes.identity.user_name -}}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.identity.email }},\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;email_verified\u0026#34;: {{ .Subject.Attributes.identity.email_verified }},\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ if $user_name -}}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;name\u0026#34;: {{ quote $user_name }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ else -}}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;name\u0026#34;: {{ quote $email }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ end -}}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eerror_handlers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticate_with_kratos\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Catalogue","url":"/docs/mechanisms/catalogue/"},{"categories":null,"content":" E.g. in one case, you want to have access to a particular request header. In another case you would like to add specific data to the resulting JWT created by heimdall. And in yet another case, you may want to check whether some expectations apply. These capabilities are described on this page.\nObjects Objects represent state in the execution of a particular rule. These are the entities, either created or used by particular mechanisms and can represent things, like the actual request, the authenticated subject of the request and many more.\nSubject This object is created by an authenticator which was able to verify the authentication claim available in the request, and contains the information about the authenticated subject. It has the following properties:\nID: string\nThe identifier of the subject.\nAttributes: map\nContains all attributes, which are known about the subject.\nEach object of this type can be thought as a JSON object. Here some examples:\nExample 1. Subject created by an Anonymous Authenticator Subject = { ID: \u0026#34;anonymous\u0026#34;, Attributes: {} } Example 2. Possible Subject created by an OAuth2 Authenticator Subject = { ID: \u0026#34;foobar\u0026#34;, Attributes: { \u0026#34;sub\u0026#34;: \u0026#34;foobar\u0026#34;, \u0026#34;exp\u0026#34;: \u0026#34;1670600805\u0026#34;, \u0026#34;jti\u0026#34;: \u0026#34;7b91ed8a-0251-4e02-8d51-9792785851e8\u0026#34;, \u0026#34;iat\u0026#34;: \u0026#34;1670600305\u0026#34;, \u0026#34;iss\u0026#34;: \u0026#34;https://testauthserver.local\u0026#34;, \u0026#34;nbf\u0026#34;: \u0026#34;1670600305\u0026#34;, \u0026#34;extra\u0026#34;: { \u0026#34;foo\u0026#34;: [\u0026#34;bar\u0026#34;, \u0026#34;baz\u0026#34;] } } } Request This object contains information about the request handled by heimdall and has the following attributes and methods:\nMethod: string\nThe HTTP method used, like GET, POST, etc.\nURL: URL\nThe URL of the matched request. This object has the following properties and methods:\nCaptures: map\nAllows accessing of the values captured by the named wildcards used in the matching path expression of the rule.\nHost: string\nThe host part of the url.\nHostname(): method\nThis method returns the host name stripping any valid port number if present.\nPort(): method\nReturns the port part of the Host, without the leading colon. If Host doesn’t contain a valid numeric port, returns an empty string.\nPath: string\nThe path part of the url.\nQuery(): method\nThe parsed query with each key-value pair being a string to array of strings mapping.\nRawQuery: string\nThe raw query part of the url.\nScheme: string\nThe HTTP scheme part of the url.\nString(): method\nThis method returns the URL as valid URL string of a form scheme:host/path?query.\nClientIPAddresses: string array\nThe list of IP addresses the request passed through with the first entry being the ultimate client of the request. Only available if heimdall is configured to trust the client, sending this information, e.g. in the X-Forwarded-From header (see also trusted_proxies configuration for more details).\nHeader(name): method,\nThis method expects the name of a header as input and returns its value as a string. If the header is not present in the HTTP request an empty string (\u0026#34;\u0026#34;) is returned. If a header appears multiple times in the request, the returned string is a comma separated list of all values.\nA single header may be a comma separated list of actual values as well. Best example is the Accept header, which might be set to e.g. text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8). Cookie(name): method,\nThis method expects the name of a cookie as input and returns the value of it as string. If the cookie is not present in the HTTP request an empty string (\u0026#34;\u0026#34;) is returned.\nBody(): method,\nThe parsed body with contents depending on the Content-Type header. Supported content types are any MIME types with json or yaml subtype, as well as application/x-www-form-urlencoded. If MIME type is unsupported, the method returns a string with the actual body contents.\nThe actual request body is parsed only on the first use of this function. All subsequent calls return the cached result. Example 3. Example results If the Content-Type header is set to application/json and the actual request body is a valid JSON object, shown below\n{ \u0026#34;context\u0026#34;: \u0026#34;heimdall\u0026#34; } The call to the Body() function will return exactly this representation as a map.\nIf the Content-Type header is set to application/yaml and the actual request body is a valid YAML object, shown below\ncontext: heimdall The call to the Body() function will return { \u0026#34;context\u0026#34;: \u0026#34;heimdall\u0026#34; } representation as a map.\nIf the Content-Type header is set to application/x-www-form-urlencoded and the actual request body is a valid object, shown below\ncontext=heimdall The call to the Body() function will return this representation as a map with each value being a string array. In this particular case as { \u0026#34;context\u0026#34;: [ \u0026#34;heimdall\u0026#34; ] }.\nHere is an example for a request object:\nExample 4. Example request object Request = { Method: \u0026#34;GET\u0026#34;, Url: { Scheme: \u0026#34;https\u0026#34;, Host: \u0026#34;localhost\u0026#34;, Path: \u0026#34;/test/abc\u0026#34;, RawQuery: \u0026#34;baz=zab\u0026amp;baz=bar\u0026amp;foo=bar\u0026#34;, Captures: { \u0026#34;value\u0026#34;: \u0026#34;abc\u0026#34; } }, ClientIP: [\u0026#34;127.0.0.1\u0026#34;, \u0026#34;10.10.10.10\u0026#34;] } Outputs This object represents a pipeline execution specific key value map. It is used by pipeline steps to store or read results of particular step executions. Mechanism id used by a pipeline step is used as a key and the value is the corresponding result.\nExample:\nOutputs = { \u0026#34;id_1\u0026#34;: [\u0026#34;a\u0026#34;, \u0026#34;b\u0026#34;], \u0026#34;id_2\u0026#34;: { \u0026#34;foo\u0026#34;: \u0026#34;bar\u0026#34;, \u0026#34;baz\u0026#34;: false } } Payload This object represents the contents of a payload, like the request body or a response body. The contents depend on the MIME-Type of the payload. For json, yaml or x-www-form-urlencoded encoded payload, the object is transformed to a JSON object. Otherwise, it is just a string.\nHere some examples:\nExample 5. Structured payload The following JSON object is a typical response from OPA.\nPayload = { \u0026#34;result\u0026#34;: true } Example 6. Unstructured payload Payload = \u0026#34;SomeStringValue\u0026#34; Error This object represents an error, which has been raised during the execution of a rule and is available in if CEL expressions of Error Handlers. Following properties are available:\nSource: string\nThe ID of the mechanism, which raised the error.\nProper error handling requires attention to the actual error type available via type(Error).\nValues This object represents a key value map, with both, the key and the value being of string type. Though, the actual values can be templated (see (Templating). The contents and the variables available in templates depend on the configuration of the particular mechanism, respectively the corresponding override in a rule.\nHere is an example:\nExample 7. Example values object Values = { \u0026#34;some-key-1\u0026#34;: \u0026#34;value-1\u0026#34;, \u0026#34;some-key-2\u0026#34;: \u0026#34;value-2\u0026#34; } Templating Some mechanisms support templating using Golang Text Templates. Templates can act on all objects described above (Subject, Outputs, Request, Payload and Values). Which exactly are supported is mechanism specific.\nTo ease the usage, all sprig functions, except env and expandenv, as well as the following functions are available:\nurlenc - Encodes a given string using url encoding. Is handy if you need to generate request body or query parameters e.g. for communication with further systems.\natIndex - Implements python-like access to arrays and takes as a single argument the index to access the element in the array at. With index being a positive values it works exactly the same way, as with the usage of the build-in index function to access array elements. With negative index value, one can access the array elements from the tail of the array. -1 is the index of the last element, -2 the index of the element before the last one, etc.\nExample: {{ atIndex 2 [1,2,3,4,5] }} evaluates to 3 (behaves the same way as the index function) and {{ atIndex -2 [1,2,3,4,5] }} evaluates to 4.\nsplitList - Splits a given string using a separator (part of the sprig library, but not documented). The result is a string array.\nExample: {{ splitList \u0026#34;/\u0026#34; \u0026#34;/foo/bar\u0026#34; }} evaluates to the [\u0026#34;\u0026#34;, \u0026#34;foo\u0026#34;, \u0026#34;bar\u0026#34;] array.\nExample 8. Rendering a JSON object Imagine, we have a POST request for the URL https://foobar.baz/zab?foo=bar, with a header X-Foo set to bar value, for which heimdall was able to identify a subject, with ID=foo and which Attributes contain an entry email: foo@bar, then you can generate a JSON object with this information with the following template:\n{ \u0026#34;subject_id\u0026#34;: {{ quote .Subject.ID }}, \u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.email }}, \u0026#34;request_url\u0026#34;: {{ quote .Request.URL }}, \u0026#34;foo_value\u0026#34;: {{ index .Request.URL.Query.foo 0 | quote }} \u0026#34;request_method\u0026#34;: {{ quote .Request.Method }}, \u0026#34;x_foo_value\u0026#34;: {{ .Request.Header \u0026#34;X-Foo\u0026#34; | quote }}, \u0026#34;whatever\u0026#34;: {{ .Outputs.whatever | quote }} } Please note how the access to the foo query parameter is done. Since .Request.URL.Query.foo returns an array of strings, the first element is taken to render the value for the foo_value key.\nThis will result in the following JSON object:\n{ \u0026#34;subject_id\u0026#34;: \u0026#34;foo\u0026#34;, \u0026#34;email\u0026#34;: \u0026#34;foo@bar.baz\u0026#34;, \u0026#34;request_url\u0026#34;: \u0026#34;https://foobar.baz/zab?foo=bar\u0026#34;, \u0026#34;foo_value\u0026#34;: \u0026#34;bar\u0026#34;, \u0026#34;request_method\u0026#34;: \u0026#34;POST\u0026#34;, \u0026#34;x_foo_value\u0026#34;: \u0026#34;bar\u0026#34;, \u0026#34;whatever\u0026#34;: \u0026#34;some value\u0026#34; } Example 9. Access to captured path segments Imagine, we have a POST request to the URL https://foobar.baz/zab/1234, with 1234 being the identifier of a file, which should be updated with the contents sent in the body of the request, and you would like to control access to the aforesaid object using e.g. OpenFGA. This can be achieved with the following authorizer:\nid: openfga_authorizer type: remote config: endpoint: url: https://openfga/stores/files/check payload: | { \u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;, \u0026#34;relation\u0026#34;: \u0026#34;write\u0026#34;, \u0026#34;object\u0026#34;: \u0026#34;file:{{ .Request.URL.Captures.id }}\u0026#34; } expressions: - expression: | Payload.allowed == true Please note how the \u0026#34;object\u0026#34; is set in the payload property above. When the payload template is rendered and for the above said request heimdall was able to identify the subject with ID=foo, following JSON object will be created:\n{ \u0026#34;user\u0026#34;: \u0026#34;user:foo\u0026#34;, \u0026#34;relation\u0026#34;: \u0026#34;write\u0026#34;, \u0026#34;object\u0026#34;: \u0026#34;file:1234\u0026#34; } You can find further examples as part of mechanism descriptions, supporting templating.\nExpressions Expressions can be used to execute conditional logic. As of today only CEL is supported as expression language. All standard, as well as extension functions are available. Which of the evaluation objects are available to the expression depends on the mechanism.\nIn addition to the build-in, respectively extension methods and functions, as well as the methods available on the evaluation objects, following functions are available as well:\nsplit - this function works on strings and expects a separator as a single argument. The result is a string array.\nExample: \u0026#34;/foo/bar/baz\u0026#34;.split(\u0026#34;/\u0026#34;) returns [\u0026#34;\u0026#34;, \u0026#34;foo\u0026#34;, \u0026#34;bar\u0026#34;, \u0026#34;baz\u0026#34;].\nregexFind - this function returns the first (left most) match of a regular expression in the given string.\nExample: \u0026#34;abcd1234\u0026#34;.regexFind(\u0026#34;[a-zA-Z][1-9]\u0026#34;) returns \u0026#34;d1\u0026#34;.\nregexFindAll - this function returns an array of all matches of a regular expression in the given string.\nExample: \u0026#34;123456789\u0026#34;.regexFindAll(\u0026#34;[2,4,6,8]\u0026#34;) returns [\u0026#34;2\u0026#34;,\u0026#34;4\u0026#34;,\u0026#34;6\u0026#34;,\u0026#34;8\u0026#34;].\nat - this function implements python-like access to arrays and takes as a single argument the index to access the element in the array at. With index being a positive values it works exactly the same way, as with the usage of [] to access array elements. With negative index value, one can access the array elements from the tail of the array. -1 is the index of the last element, -2 the index of the element before the last one, etc.\nExample: [1,2,3,4,5].at(2) returns 3 and [1,2,3,4,5].at(-2) returns 4.\nlast - this function works on arrays and returns the last element of an array or nil if the array is empty.\nExample: [1,2,3,4,5].last() returns 5\nSome examples:\nExample 10. Evaluate Payload object Given the following Payload object\nPayload = { \u0026#34;result\u0026#34;: true } a CEL expression to check whether the result attribute is set to true, would look as follows:\nPayload.result == true Example 11. Check whether the user is member of the admin group has(Subject.Attributes.groups) \u0026amp;\u0026amp; Subject.Attributes.groups.exists(g, g == \u0026#34;admin\u0026#34;) Example 12. Access the last path part of the matched URL Request.URL.Path.split(\u0026#34;/\u0026#34;).last() Example 13. Check if an error has been raised by an authenticator with the ID \u0026#34;foo\u0026#34; type(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;foo\u0026#34; ","description":"The dynamic nature of mechanisms is given by the ability to work on different objects and making use of templates and expressions to implement different use cases.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g. in one case, you want to have access to a particular request header. In another case you would like to add specific data to the resulting JWT created by heimdall. And in yet another case, you may want to check whether some expectations apply. These capabilities are described on this page.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_objects\"\u003eObjects\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eObjects represent state in the execution of a particular rule. These are the entities, either created or used by particular mechanisms and can represent things, like the actual request, the authenticated subject of the request and many more.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_subject\"\u003eSubject\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object is created by an authenticator which was able to verify the authentication claim available in the request, and contains the information about the authenticated subject. It has the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eID\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe identifier of the subject.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eAttributes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emap\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eContains all attributes, which are known about the subject.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach object of this type can be thought as a JSON object. Here some examples:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Subject created by an Anonymous Authenticator\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003eSubject\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"na\"\u003eID\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eanonymous\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eAttributes\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Possible Subject created by an OAuth2 Authenticator\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003eSubject\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"na\"\u003eID\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003efoobar\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eAttributes\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003esub\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003efoobar\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eexp\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e1670600805\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ejti\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e7b91ed8a-0251-4e02-8d51-9792785851e8\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eiat\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e1670600305\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eiss\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ehttps://testauthserver.local\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003enbf\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e1670600305\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eextra\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003efoo\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ebar\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ebaz\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_request\"\u003eRequest\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object contains information about the request handled by heimdall and has the following attributes and methods:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eMethod\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe HTTP method used, like \u003ccode\u003eGET\u003c/code\u003e, \u003ccode\u003ePOST\u003c/code\u003e, etc.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv id=\"_url_captures\" class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eURL\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eURL\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe URL of the matched request. This object has the following properties and methods:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eCaptures\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emap\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAllows accessing of the values captured by the named wildcards used in the matching path expression of the rule.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eHost\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe host part of the url.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eHostname()\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis method returns the host name stripping any valid port number if present.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ePort()\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eReturns the port part of the \u003ccode\u003eHost\u003c/code\u003e, without the leading colon. If \u003ccode\u003eHost\u003c/code\u003e doesn’t contain a valid numeric port, returns an empty string.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ePath\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe path part of the url.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eQuery()\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe parsed query with each key-value pair being a string to array of strings mapping.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eRawQuery\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe raw query part of the url.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eScheme\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe HTTP scheme part of the url.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eString()\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis method returns the URL as valid URL string of a form \u003ccode\u003escheme:host/path?query\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eClientIPAddresses\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe list of IP addresses the request passed through with the first entry being the ultimate client of the request. Only available if heimdall is configured to trust the client, sending this information, e.g. in the \u003ccode\u003eX-Forwarded-From\u003c/code\u003e header (see also \u003ca href=\"/docs/services/main/#_trusted_proxies\"\u003etrusted_proxies\u003c/a\u003e configuration for more details).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eHeader(name)\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e,\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis method expects the name of a header as input and returns its value as a \u003ccode\u003estring\u003c/code\u003e. If the header is not present in the HTTP request an empty string (\u003ccode\u003e\u0026#34;\u0026#34;\u003c/code\u003e) is returned. If a header appears multiple times in the request, the returned \u003ccode\u003estring\u003c/code\u003e is a comma separated list of all values.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nA single header may be a comma separated list of actual values as well. Best example is the \u003ccode\u003eAccept\u003c/code\u003e header, which might be set to e.g. \u003ccode\u003etext/html,application/xhtml+xml,application/xml;q=0.9,\u003cstrong\u003e/\u003c/strong\u003e;q=0.8\u003c/code\u003e).\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eCookie(name)\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e,\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis method expects the name of a cookie as input and returns the value of it as \u003ccode\u003estring\u003c/code\u003e. If the cookie is not present in the HTTP request an empty string (\u003ccode\u003e\u0026#34;\u0026#34;\u003c/code\u003e) is returned.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eBody()\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emethod\u003c/em\u003e,\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe parsed body with contents depending on the \u003ccode\u003eContent-Type\u003c/code\u003e header. Supported content types are any MIME types with \u003ccode\u003ejson\u003c/code\u003e or \u003ccode\u003eyaml\u003c/code\u003e subtype, as well as \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e. If MIME type is unsupported, the method returns a string with the actual body contents.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe actual request body is parsed only on the first use of this function. All subsequent calls return the cached result.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Example results\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003eContent-Type\u003c/code\u003e header is set to \u003ccode\u003eapplication/json\u003c/code\u003e and the actual request body is a valid JSON object, shown below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;context\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;heimdall\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe call to the \u003ccode\u003eBody()\u003c/code\u003e function will return exactly this representation as a map.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003eContent-Type\u003c/code\u003e header is set to \u003ccode\u003eapplication/yaml\u003c/code\u003e and the actual request body is a valid YAML object, shown below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003econtext\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe call to the \u003ccode\u003eBody()\u003c/code\u003e function will return \u003ccode\u003e{ \u0026#34;context\u0026#34;: \u0026#34;heimdall\u0026#34; }\u003c/code\u003e representation as a map.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003eContent-Type\u003c/code\u003e header is set to \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e and the actual request body is a valid object, shown below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"s\"\u003econtext=heimdall\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe call to the \u003ccode\u003eBody()\u003c/code\u003e function will return this representation as a map with each value being a string array. In this particular case as \u003ccode\u003e{ \u0026#34;context\u0026#34;: [ \u0026#34;heimdall\u0026#34; ] }\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere is an example for a request object:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Example request object\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003eRequest\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"na\"\u003eMethod\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eGET\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eUrl\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"na\"\u003eScheme\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ehttps\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eHost\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003elocalhost\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003ePath\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e/test/abc\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eRawQuery\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ebaz=zab\u0026amp;baz=bar\u0026amp;foo=bar\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"na\"\u003eCaptures\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003evalue\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eabc\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n \u003cspan class=\"na\"\u003eClientIP\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e127.0.0.1\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003e10.10.10.10\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_outputs\"\u003eOutputs\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object represents a pipeline execution specific key value map. It is used by pipeline steps to store or read results of particular step executions. Mechanism id used by a pipeline step is used as a key and the value is the corresponding result.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003eOutputs\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eid_1\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ea\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eb\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eid_2\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003efoo\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ebar\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003ebaz\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_payload\"\u003ePayload\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object represents the contents of a payload, like the request body or a response body. The contents depend on the MIME-Type of the payload. For \u003ccode\u003ejson\u003c/code\u003e, \u003ccode\u003eyaml\u003c/code\u003e or \u003ccode\u003ex-www-form-urlencoded\u003c/code\u003e encoded payload, the object is transformed to a JSON object. Otherwise, it is just a string.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere some examples:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Structured payload\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following JSON object is a typical response from OPA.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003ePayload\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eresult\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 6. Unstructured payload\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003ePayload\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eSomeStringValue\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_error\"\u003eError\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object represents an error, which has been raised during the execution of a rule and is available in \u003ccode\u003eif\u003c/code\u003e \u003ca href=\"#_expressions\"\u003eCEL expressions\u003c/a\u003e of \u003ca href=\"/docs/mechanisms/error_handlers/\"\u003eError Handlers\u003c/a\u003e. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eSource\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe ID of the mechanism, which raised the error.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eProper error handling requires attention to the actual \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_errorstate_type\"\u003eerror type\u003c/a\u003e\u003c/em\u003e available via \u003ccode\u003etype(Error)\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_values\"\u003eValues\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis object represents a key value map, with both, the key and the value being of string type. Though, the actual values can be templated (see (\u003ca href=\"#_templating\"\u003eTemplating\u003c/a\u003e). The contents and the variables available in templates depend on the configuration of the particular mechanism, respectively the corresponding override in a rule.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere is an example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 7. Example values object\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003eValues\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003esome-key-1\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003evalue-1\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003esome-key-2\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003evalue-2\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_templating\"\u003eTemplating\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome mechanisms support templating using \u003ca href=\"https://golang.org/pkg/text/template/\"\u003eGolang Text Templates\u003c/a\u003e. Templates can act on all objects described above (\u003ca href=\"#_subject\"\u003eSubject\u003c/a\u003e, \u003ca href=\"#_outputs\"\u003eOutputs\u003c/a\u003e, \u003ca href=\"#_request\"\u003eRequest\u003c/a\u003e, \u003ca href=\"#_payload\"\u003ePayload\u003c/a\u003e and \u003ca href=\"#_values\"\u003eValues\u003c/a\u003e). Which exactly are supported is mechanism specific.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo ease the usage, all \u003ca href=\"https://masterminds.github.io/sprig/\"\u003esprig\u003c/a\u003e functions, except \u003ccode\u003eenv\u003c/code\u003e and \u003ccode\u003eexpandenv\u003c/code\u003e, as well as the following functions are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eurlenc\u003c/code\u003e - Encodes a given string using url encoding. Is handy if you need to generate request body or query parameters e.g. for communication with further systems.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eatIndex\u003c/code\u003e - Implements python-like access to arrays and takes as a single argument the index to access the element in the array at. With index being a positive values it works exactly the same way, as with the usage of the build-in index function to access array elements. With negative index value, one can access the array elements from the tail of the array. -1 is the index of the last element, -2 the index of the element before the last one, etc.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e{{ atIndex 2 [1,2,3,4,5] }}\u003c/code\u003e evaluates to \u003ccode\u003e3\u003c/code\u003e (behaves the same way as the \u003ccode\u003eindex\u003c/code\u003e function) and \u003ccode\u003e{{ atIndex -2 [1,2,3,4,5] }}\u003c/code\u003e evaluates to \u003ccode\u003e4\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003esplitList\u003c/code\u003e - Splits a given string using a separator (part of the sprig library, but not documented). The result is a string array.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e{{ splitList \u0026#34;/\u0026#34; \u0026#34;/foo/bar\u0026#34; }}\u003c/code\u003e evaluates to the \u003ccode\u003e[\u0026#34;\u0026#34;, \u0026#34;foo\u0026#34;, \u0026#34;bar\u0026#34;]\u003c/code\u003e array.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 8. Rendering a JSON object\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine, we have a \u003ccode\u003ePOST\u003c/code\u003e request for the URL \u003ccode\u003ehttps://foobar.baz/zab?foo=bar\u003c/code\u003e, with a header \u003ccode\u003eX-Foo\u003c/code\u003e set to \u003ccode\u003ebar\u003c/code\u003e value, for which heimdall was able to identify a subject, with \u003ccode\u003eID=foo\u003c/code\u003e and which \u003ccode\u003eAttributes\u003c/code\u003e contain an entry \u003ccode\u003eemail: foo@bar\u003c/code\u003e, then you can generate a JSON object with this information with the following template:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"gotemplate\"\u003e{\n \u0026#34;subject_id\u0026#34;: {{ quote .Subject.ID }},\n \u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.email }},\n \u0026#34;request_url\u0026#34;: {{ quote .Request.URL }},\n \u0026#34;foo_value\u0026#34;: {{ index .Request.URL.Query.foo 0 | quote }}\n \u0026#34;request_method\u0026#34;: {{ quote .Request.Method }},\n \u0026#34;x_foo_value\u0026#34;: {{ .Request.Header \u0026#34;X-Foo\u0026#34; | quote }},\n \u0026#34;whatever\u0026#34;: {{ .Outputs.whatever | quote }}\n}\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePlease note how the access to the \u003ccode\u003efoo\u003c/code\u003e query parameter is done. Since \u003ccode\u003e.Request.URL.Query.foo\u003c/code\u003e returns an array of strings, the first element is taken to render the value for the \u003ccode\u003efoo_value\u003c/code\u003e key.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis will result in the following JSON object:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;subject_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;foo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;foo@bar.baz\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;request_url\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://foobar.baz/zab?foo=bar\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;foo_value\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;bar\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;request_method\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;POST\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;x_foo_value\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;bar\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;whatever\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;some value\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 9. Access to captured path segments\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine, we have a \u003ccode\u003ePOST\u003c/code\u003e request to the URL \u003ccode\u003ehttps://foobar.baz/zab/1234\u003c/code\u003e, with \u003ccode\u003e1234\u003c/code\u003e being the identifier of a file, which should be updated with the contents sent in the body of the request, and you would like to control access to the aforesaid object using e.g. OpenFGA. This can be achieved with the following authorizer:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_authorizer\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://openfga/stores/files/check\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;user\u0026#34;: \u0026#34;user:{{ .Subject.ID }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;relation\u0026#34;: \u0026#34;write\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;object\u0026#34;: \u0026#34;file:{{ .Request.URL.Captures.id }}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.allowed == true\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePlease note how the \u003ccode\u003e\u0026#34;object\u0026#34;\u003c/code\u003e is set in the \u003ccode\u003epayload\u003c/code\u003e property above. When the \u003ccode\u003epayload\u003c/code\u003e template is rendered and for the above said request heimdall was able to identify the subject with \u003ccode\u003eID=foo\u003c/code\u003e, following JSON object will be created:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;user\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;user:foo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;relation\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;write\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;object\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;file:1234\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYou can find further examples as part of mechanism descriptions, supporting templating.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_expressions\"\u003eExpressions\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExpressions can be used to execute conditional logic. As of today only \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e is supported as expression language. All standard, as well as \u003ca href=\"https://pkg.go.dev/github.com/google/cel-go/ext#pkg-functions\"\u003eextension\u003c/a\u003e functions are available. Which of the \u003ca href=\"#_objects\"\u003eevaluation objects\u003c/a\u003e are available to the expression depends on the mechanism.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition to the build-in, respectively extension methods and functions, as well as the methods available on the evaluation objects, following functions are available as well:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003esplit\u003c/code\u003e - this function works on strings and expects a separator as a single argument. The result is a string array.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e\u0026#34;/foo/bar/baz\u0026#34;.split(\u0026#34;/\u0026#34;)\u003c/code\u003e returns \u003ccode\u003e[\u0026#34;\u0026#34;, \u0026#34;foo\u0026#34;, \u0026#34;bar\u0026#34;, \u0026#34;baz\u0026#34;]\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eregexFind\u003c/code\u003e - this function returns the first (left most) match of a regular expression in the given string.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e\u0026#34;abcd1234\u0026#34;.regexFind(\u0026#34;[a-zA-Z][1-9]\u0026#34;)\u003c/code\u003e returns \u003ccode\u003e\u0026#34;d1\u0026#34;\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eregexFindAll\u003c/code\u003e - this function returns an array of all matches of a regular expression in the given string.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e\u0026#34;123456789\u0026#34;.regexFindAll(\u0026#34;[2,4,6,8]\u0026#34;)\u003c/code\u003e returns \u003ccode\u003e[\u0026#34;2\u0026#34;,\u0026#34;4\u0026#34;,\u0026#34;6\u0026#34;,\u0026#34;8\u0026#34;]\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eat\u003c/code\u003e - this function implements python-like access to arrays and takes as a single argument the index to access the element in the array at. With index being a positive values it works exactly the same way, as with the usage of \u003ccode\u003e[]\u003c/code\u003e to access array elements. With negative index value, one can access the array elements from the tail of the array. -1 is the index of the last element, -2 the index of the element before the last one, etc.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e[1,2,3,4,5].at(2)\u003c/code\u003e returns \u003ccode\u003e3\u003c/code\u003e and \u003ccode\u003e[1,2,3,4,5].at(-2)\u003c/code\u003e returns \u003ccode\u003e4\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003elast\u003c/code\u003e - this function works on arrays and returns the last element of an array or \u003ccode\u003enil\u003c/code\u003e if the array is empty.\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExample: \u003ccode\u003e[1,2,3,4,5].last()\u003c/code\u003e returns \u003ccode\u003e5\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome examples:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 10. Evaluate Payload object\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eGiven the following Payload object\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"javascript\"\u003e\u003cspan class=\"nx\"\u003ePayload\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s2\"\u003eresult\u003c/span\u003e\u003cspan class=\"dl\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ea CEL expression to check whether the \u003ccode\u003eresult\u003c/code\u003e attribute is set to \u003ccode\u003etrue\u003c/code\u003e, would look as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"cel\"\u003ePayload.result == true\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 11. Check whether the user is member of the admin group\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"cel\"\u003ehas(Subject.Attributes.groups) \u0026amp;\u0026amp;\n Subject.Attributes.groups.exists(g, g == \u0026#34;admin\u0026#34;)\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 12. Access the last path part of the matched URL\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"cel\"\u003eRequest.URL.Path.split(\u0026#34;/\u0026#34;).last()\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 13. Check if an error has been raised by an authenticator with the ID \u0026#34;foo\u0026#34;\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"cel\"\u003etype(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;foo\u0026#34;\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Objects, Templating \u0026 Co","url":"/docs/mechanisms/evaluation_objects/"},{"categories":null,"content":" Some of the supported authenticator types may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overriddable and partially overridable to indicate whether the property can be overridden in a rule pipeline.\nUnauthorized This authenticator rejects all requests as unauthenticated (on HTTP response code level this is then mapped to 401 Unauthorized, hence the type name). It basically stops the successful execution of the pipeline resulting in the execution of the error handlers. This authenticator type doesn’t have any configuration options.\nTo enable the usage of this authenticator, you have to set the type property to unauthorized.\nExample 1. Configure Unauthorized authenticator id: foo type: unauthorized Anonymous This authenticator just creates a Subject object and sets its ID to anonymous without doing anything else. You can overwrite the value of subject’s id by using the optional config property.\nTo enable the usage of this authenticator, you have to set the type property to anonymous.\nConfiguration using the config property is optional. Following properties are available:\nsubject: string (optional, overridable)\nEnables setting the ID of the created Subject object to a custom value.\nExample 2. Configuration of Anonymous authenticator id: foo type: anonymous config: subject: anon Basic Auth This authenticator verifies the provided credentials according to the HTTP \u0026#34;Basic\u0026#34; authentication scheme, described in RFC 7617. It does however not challenge the authentication, it only verifies the provided credentials and sets the Subject ID to the configured user identifier if the authentication succeeds. Otherwise, it raises an error, resulting in the execution of the configured error handlers. The \u0026#34;WWW Authenticate\u0026#34; error handler mechanism can for example be used if the corresponding challenge is required.\nTo enable the usage of this authenticator, you have to set the type property to basic_auth.\nConfiguration using the config property is mandatory. Following properties are available:\nuser_id: string (mandatory, overridable)\nThe identifier of the subject to be verified.\npassword: string (mandatory, overridable)\nThe password of the subject to be verified.\nallow_fallback_on_error: boolean (optional, overridable)\nIf set to true, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to false.\nExample 3. Configuration of Basic Auth authenticator id: foo type: basic_auth config: user_id: bar password: baz Generic This authenticator is kind of a Swiss knife and can do a lot depending on the given configuration. It verifies the authentication status of the subject by making use of values available in cookies, headers, or query parameters of the HTTP request and communicating with the actual authentication system to perform the verification of the subject authentication status on the one hand, and to get the information about the subject on the other hand. There is however one limitation: it can only deal with JSON responses.\nTo enable the usage of this authenticator, you have to set the type property to generic.\nConfiguration using the config property is mandatory. Following properties are available:\nidentity_info_endpoint: Endpoint (mandatory, not overridable)\nThe endpoint to communicate to for the actual subject authentication status verification purpose. At least the url must be configured. If you don’t configure method, HTTP POST will be used. The Accept header is set to application/json by default. You can overwrite these setting if required. Query and header definitions can be templated and can make use of the AuthenticationData object (see below). Don’t forget - this authenticator supports only JSON responses.\nauthentication_data_source: Authentication Data Source (mandatory, not overridable)\nWhere to extract the authentication data from the request. The extracted value is made available as AuthenticationData for usage in templates defined as part of this authenticator configuration. So you can reference it in a body, header, etc.\nThe AuthenticationData object is available during the execution of this authenticator only and is not made available to other mechanisms. forward_headers: string array (optional, not overridable)\nIf the identity_info_endpoint API requires any headers from the request to heimdall, you can forward these unchanged by making use of this property. This might be the header used to extract the authentication data from.\nforward_cookies: string array (optional, not overridable)\nIf the identity_info_endpoint API requires any cookies from the request to heimdall, you can forward these unchanged by making use of this property. This might be the cookie used to extract the authentication data from.\npayload: string (optional, not overridable)\nYour template with definitions required to send the extracted authentication data. The template has access to the AuthenticationData object only.\nsubject: Subject (mandatory, not overridable)\nWhere to extract the Subject information from the identity info endpoint response.\ncache_ttl: Duration (optional, overridable)\nHow long to cache the response. If not set, response caching if disabled. The cache key is calculated from the identity_info_endpoint configuration and the actual authentication data value.\nallow_fallback_on_error: boolean (optional, overridable)\nIf set to true, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to false.\nsession_lifespan: Session Lifespan (optional, not overridable)\nWhere to extract the session validity information form the identity info endpoint response. If the not_after property is specified, the corresponding value from the response is also used for cache ttl calculation to prevent usage of not anymore valid session objects and overwrites the value configured for cache_ttl if the usage of that value would exceed the lifespan of the session object.\nIf you’re configuring the cache_ttl property, it is highly recommended to configure session_lifespan as well to ensure outdated session objects are not used for subsequent requests to heimdall. Usage of session_lifespan is recommended anyway to enable time based validation of the response from the identity info endpoint. Example 4. Configuration to work with session cookies This example shows how to configure this authenticator to work with Ory Kratos, an authentication system, which issues a cookie upon successful user authentication to maintain the authentication state. To reduce the communication overhead, it also makes use of cache_ttl to cache the response for 5 minutes if that time frame does not exceed the actual validity of the session represented by the cookie.\nid: kratos_session_cookie type: generic config: identity_info_endpoint: https://kratos/sessions/whoami authentication_data_source: - cookie: ory_kratos_session forward_cookies: - ory_kratos_session subject: id: \u0026#34;identity.id\u0026#34; cache_ttl: 5m session_lifespan: active: active issued_at: issued_at not_before: authenticated_at not_after: expires_at time_format: \u0026#34;2006-01-02T15:04:05.999999Z07\u0026#34; validity_leeway: 10s As kratos requires the ory_kratos_session cookie as is, this configuration makes use of the forward_cookies property and does not use the AuthenticationData object.\nThis example does also show how an endpoint can be configured by just specifying the URL as string, which is the simplest way for endpoint configuration.\nExample 5. Configuration to work with a Bearer token This example shows how to configure this authenticator to work with an OAuth2 authorization service, which issues a Bearer token upon successful user authentication. To reduce the communication overhead, it also makes use of cache_ttl to cache the response for 5 minutes if it does not exceed the validity of the information present in the response from the used endpoint.\nIn this example we configure the authenticator to use the introspection endpoint to get the information about the token.\nid: opaque_bearer_token type: generic config: identity_info_endpoint: url: https://my-auth.system/introspect headers: Content-Type: application/x-www-form-urlencoded auth: type: basic_auth config: user: Heimdall password: ${INTROSPECTION_PASSWORD} authentication_data_source: - header: Authorization scheme: Bearer payload: | token={{ urlenc .AuthenticationData }}\u0026amp;token_type_hint=access_token subject: id: sub cache_ttl: 5m session_lifespan: active: active issued_at: iat not_before: nbf not_after: exp validity_leeway: 10s Usually, you would not only like to verify the validity of a token, but also a couple of claims. This can be achieved by a CEL Authorizer. However, there is also a special purpose OAuth2 Introspection authenticator type, which supports asserting all security relevant claims in just one place and does not need so much configuration as shown above.\nIn this configuration the authenticator extracts the token from the Authorization header and request the information about the corresponding user from the https://my-auth.system/introspect endpoint by sending the extracted token in the body of the request in a parameter named token.\nExample 6. Configuration to work with Google’s Firebase. If you would like to integrate with Google’s Firebase, you would configure something like this:\nAssumption: The token issued by firebase is located in the HTTP Authorization header using Bearer scheme\nid: firebase_token type: generic config: identity_info_endpoint: url: https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${YOUR_API_KEY} headers: Content-Type: application/json authentication_data_source: - header: Authorization scheme: Bearer payload: | { \u0026#34;idToken\u0026#34;: {{ quote .AuthenticationData }} } subject: id: users.0.localId attributes: users.0 cache_ttl: 5m OAuth2 Introspection This authenticator handles requests that have Bearer token in the HTTP Authorization header (Authorization: Bearer \u0026lt;token\u0026gt;), in the access_token query parameter or the access_token body parameter (latter, if the body is of application/x-www-form-urlencoded MIME type). It then uses OAuth 2.0 Token Introspection endpoint to check if the token is valid. The validation includes at least the verification of the status and the time validity. That is if the token is still active and whether it has been issued in an acceptable time frame. Latter can be adjusted by specifying a leeway. All other validation options can and should be configured.\nTo enable the usage of this authenticator, you have to set the type property to oauth2_introspection.\nConfiguration using the config property is mandatory. Following properties are available:\nintrospection_endpoint: Endpoint (dependant, not overridable)\nThe OAuth 2.0 Token Introspection endpoint of the OAuth2 authorization provider.\nThe configuration of this property is mutually exclusive with metadata_endpoint. If used, at least the url must be configured. There is no need to define the method property or setting the Content-Type or the Accept header. These are set by default to the values required by the RFC referenced above. You can however override these while configuring the authenticator if needed. The path part of the url can be templated and has access to the TokenIssuer object, which is a string and only available if the format of the used token is JWT. It basically holds the value of the iss claim from the token.\nmetadata_endpoint: Endpoint (dependant, not overridable)\nThe OAuth 2.0 Authorization Server Metadata endpoint of the OAuth2, respectively OIDC authorization provider (the OpenID Connect Discovery specification is an OIDC specific profile of that specification). If the token introspection URL is not known upfront, it can be resolved by making use of that endpoint.\nThe configuration of this property is mutually exclusive with introspection_endpoint. If used, at least the url must be configured, can be templated and has access to the TokenIssuer object already introduced above (with the same limitations).\nThe metadata_endpoint is by default configured to use GET as HTTP method and sets the Accept header to application/json as also required by both specifications referenced above. In addition, to avoid useless communication, it is also configured to make use of HTTP cache according to RFC 7234 with default HTTP cache ttl set to 30m. All these settings can however be overridden if required.\nIn addition to the properties specified by the endpoint type, following properties are available:\ndisable_issuer_identifier_verification: boolean (optional, not overridable)\nUpon retrieval of the server metadata, both, the OAuth 2.0 Authorization Server Metadata RFC, and the OpenID Connect Discovery specification, require the verification of the issuer identifier for security reasons, e.g. to prevent Spoofing Attacks. There are however setups, where strictly following that recommendation would result in extended bandwidth usage (instead of communicating directly with the auth server within the cluster one would need to use the same domain, the client application uses, which introduces additional network hops). It might also not work at all as the actual identifier of the issuer would change depending on where the request come from. By making use of this property and setting it to true, one can disable the corresponding verification. Defaults to false.\ntoken_source: Authentication Data Source (optional, not overridable)\nWhere to get the access token from. Defaults to retrieve it from the Authorization header, the access_token query parameter or the access_token body parameter (latter, if the body is of application/x-www-form-urlencoded MIME type).\nassertions: Assertions (dependent, overridable)\nConfigures the required claim assertions. Overriding on rule level is possible even partially. Those parts of the assertion, which have not been overridden are taken from the prototype configuration. If metadata_endpoint is used, the list of issuers is optional, as the issuer will be resolved via the auth server metadata document. Otherwise, the list of issuers is mandatory.\nsubject: Subject (optional, not overridable)\nWhere to extract the Subject information from the introspection endpoint response. If not configured sub is used to extract the subject ID and all attributes from the introspection endpoint response are made available as Attributes.\ncache_ttl: Duration (optional, overridable)\nHow long to cache the response. If not set, caching of the introspection response is based on the available token expiration information. To disable caching, set it to 0s. If you set the ttl to a custom value \u0026gt; 0, the expiration time (if available) of the token will be considered. The cache key is calculated from the introspection_endpoint configuration and the value of the access token.\nallow_fallback_on_error: boolean (optional, overridable)\nIf set to true, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to false.\nExample 7. Minimal possible configuration based on the Introspection endpoint id: at_opaque type: oauth2_introspection config: introspection_endpoint: url: https://hydra:4445/oauth2/introspect assertions: issuers: - https://127.0.0.1:4444/ Example 8. Configuration for Keycloak utilizing metadata discovery id: keycloak type: metadata_endpoint config: metadata_endpoint: url: https://keycloak:8080/realms/{{ trimPrefix \u0026#34;https://my-auth-server/realms/\u0026#34; .TokenIssuer }}/.well-known/openid-configuration # Note that no assertions are configured here, since it\u0026#39;ll be resolved via the metadata endpoint This example does also show how to make use of templating if the format of the access token is JWT.\nThe external domain of the auth server in this example is https://my-auth-server.com. If the iss claim of the issued JWT is set to https://my-auth-server.com/realms/my-app, the above line will build an internal URL to the metadata endpoint of the same server and profile/realm, which is that case would be https://keycloak:8080/realms/my-app/.well-known/openid-configuration\nJWT As the OAuth2 Introspection authenticator, this authenticator handles requests that have a Bearer token in the Authorization header, in a different header, a query parameter or a body parameter as well. Unlike the OAuth2 Introspection authenticator it expects the token to be a JSON Web Token (JWT) and verifies it according RFC 7519, Section 7.2. It does however not support encrypted payloads and nested JWTs. In addition to this, validation includes the verification of the time validity. Latter can be adjusted by specifying a leeway. All other validation options can and should be configured.\nTo enable the usage of this authenticator, you have to set the type property to jwt.\nConfiguration using the config property is mandatory. Following properties are available:\njwks_endpoint: Endpoint (dependant, not overridable)\nThe JWKS endpoint, this authenticator retrieves the key material in a format specified in RFC 7519 from for JWT signature verification purposes.\nThe configuration of this property is mutually exclusive with metadata_endpoint. If used, at least the url must be configured. By default method is set to GET and the HTTP Accept header to application/json. The path part of the url can be templated and has access to the TokenIssuer object, which is a string and basically holds the value of the iss claim from the token.\nmetadata_endpoint: Endpoint (dependant, not overridable)\nThe OAuth 2.0 Authorization Server Metadata endpoint of the OAuth2, respectively OIDC authorization provider (the OpenID Connect Discovery specification is an OIDC specific profile of that specification). If the JWKS URL is not known upfront, it can be resolved by making use of that endpoint.\nThe configuration of this property is mutually exclusive with jwks_endpoint. If used, at least the url must be configured. As with the jwks_endpoint, the path part of the url can be templated and has access to the TokenIssuer object already introduced above.\nAs with the jwks_endpoint as well, the metadata_endpoint is by default configured to use GET as HTTP method and sets the Accept header to application/json, as also required by both specifications referenced above. In addition, to avoid useless communication, it is also configured to make use of HTTP cache according to RFC 7234 with default HTTP cache ttl set to 30m. All these settings can however be overridden if required.\nIn addition to the properties specified by the endpoint type, following properties are available:\ndisable_issuer_identifier_verification: boolean (optional, not overridable)\nUpon retrieval of the server metadata, both, the OAuth 2.0 Authorization Server Metadata RFC, and the OpenID Connect Discovery specification, require the verification of the issuer identifier for security reasons, e.g. to prevent Spoofing Attacks. There are however setups, where strictly following that recommendation would result in extended bandwidth usage (instead of communicating directly with the auth server within the cluster one would need to use the same domain, the client application uses, which introduces additional network hops). It might also not work at all as the actual identifier of the issuer would change depending on where the request come from. By making use of this property and setting it to true, one can disable the corresponding verification. Defaults to false.\njwt_source: Authentication Data Source (optional, not overridable)\nWhere to get the access token from. Defaults to retrieve it from the Authorization header, the access_token query parameter or the access_token body parameter (latter, if the body is of application/x-www-form-urlencoded MIME type).\nassertions: Assertions (dependant, overridable)\nConfigures the required claim assertions. Overriding on rule level is possible even partially. Those parts of the assertion, which have not been overridden are taken from the prototype configuration. If metadata_endpoint is used, the list of issuers is optional, as the issuer will be resolved via the auth server metadata document. Otherwise, the list of issuers is mandatory.\nsubject: Subject (optional, not overridable)\nWhere to extract the subject id from the JWT, as well as which attributes to use. If not configured sub is used to extract the subject id and all attributes from the JWT payload are made available as attributes of the subject.\ncache_ttl: Duration (optional, overridable)\nHow long to cache the key from the JWKS response, which was used for signature verification purposes. If not set, heimdall will cache this key for 10 minutes and not call JWKS endpoint again if the same kid is referenced in an JWT and same JWKS endpoint is used. The cache key is calculated from the jwks_endpoint configuration and the kid referenced in the JWT.\nallow_fallback_on_error: boolean (optional, overridable)\nIf set to true, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to false.\nvalidate_jwk: boolean (optional, not overridable)\nEnables or disables the verification of the JWK certificate used for JWT signature verification purposes. Effective only if the JWK contains a certificate. The verification happens according to RFC 5280, section 6.1 and also includes the check, that the certificate is allowed to be used for signature verification purposes. Revocation check is not supported. Defaults to true.\ntrust_store: string (optional, not overridable)\nThe path to a PEM file containing the trust anchors, to be used for the JWK certificate validation. Defaults to system trust store.\nIf a JWT does not reference a kid, heimdall always fetches a JWKS from the configured endpoint (so no caching is done) and iterates over the received keys until one matches. If none matches, the authenticator fails. Example 9. Minimal possible configuration based on the JWKS endpoint id: at_jwt type: jwt config: jwks_endpoint: url: https://hydra:4444/.well-known/jwks.json assertions: issuers: - https://127.0.0.1:4444/ Example 10. Configuration for Keycloak utilizing metadata discovery id: keycloak type: jwt config: metadata_endpoint: url: https://keycloak:8080/realms/my-app/.well-known/openid-configuration # Note that no assertions are configured here, since it\u0026#39;ll be resolved via the metadata endpoint ","description":"Authenticators verify the authentication status of requests and create subjects. This page describes the available authenticator types in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome of the supported authenticator types may support or require additional configuration. The corresponding properties are annotated with \u003ccode\u003emandatory\u003c/code\u003e, respectively \u003ccode\u003eoptional\u003c/code\u003e to denote configuration requirement, as well as with \u003ccode\u003eoverridable\u003c/code\u003e, \u003ccode\u003enot overriddable\u003c/code\u003e and \u003ccode\u003epartially overridable\u003c/code\u003e to indicate whether the property can be overridden in a rule pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_unauthorized\"\u003eUnauthorized\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authenticator rejects all requests as unauthenticated (on HTTP response code level this is then mapped to \u003ccode\u003e401 Unauthorized\u003c/code\u003e, hence the type name). It basically stops the successful execution of the pipeline resulting in the execution of the error handlers. This authenticator type doesn’t have any configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eunauthorized\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Configure Unauthorized authenticator\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eunauthorized\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_anonymous\"\u003eAnonymous\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authenticator just creates a \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e object and sets its \u003ccode\u003eID\u003c/code\u003e to \u003ccode\u003eanonymous\u003c/code\u003e without doing anything else. You can overwrite the value of subject’s id by using the optional \u003ccode\u003econfig\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eanonymous\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is optional. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esubject\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables setting the \u003ccode\u003eID\u003c/code\u003e of the created \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e object to a custom value.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Configuration of Anonymous authenticator\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_basic_auth\"\u003eBasic Auth\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authenticator verifies the provided credentials according to the HTTP \u0026#34;Basic\u0026#34; authentication scheme, described in \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7617\"\u003eRFC 7617\u003c/a\u003e. It does however not challenge the authentication, it only verifies the provided credentials and sets the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e \u003ccode\u003eID\u003c/code\u003e to the configured user identifier if the authentication succeeds. Otherwise, it raises an error, resulting in the execution of the configured error handlers. The \u003ca href=\"/docs/mechanisms/error_handlers/#_www_authenticate\"\u003e\u0026#34;WWW Authenticate\u0026#34;\u003c/a\u003e error handler mechanism can for example be used if the corresponding challenge is required.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ebasic_auth\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003euser_id\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe identifier of the subject to be verified.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epassword\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe password of the subject to be verified.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_fallback_on_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf set to \u003ccode\u003etrue\u003c/code\u003e, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Configuration of Basic Auth authenticator\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebaz\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_generic\"\u003eGeneric\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authenticator is kind of a Swiss knife and can do a lot depending on the given configuration. It verifies the authentication status of the subject by making use of values available in cookies, headers, or query parameters of the HTTP request and communicating with the actual authentication system to perform the verification of the subject authentication status on the one hand, and to get the information about the subject on the other hand. There is however one limitation: it can only deal with JSON responses.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003egeneric\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eidentity_info_endpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe endpoint to communicate to for the actual subject authentication status verification purpose. At least the \u003ccode\u003eurl\u003c/code\u003e must be configured. If you don’t configure \u003ccode\u003emethod\u003c/code\u003e, HTTP \u003ccode\u003ePOST\u003c/code\u003e will be used. The \u003ccode\u003eAccept\u003c/code\u003e header is set to \u003ccode\u003eapplication/json\u003c/code\u003e by default. You can overwrite these setting if required. Query and header definitions can be templated and can make use of the \u003ccode\u003eAuthenticationData\u003c/code\u003e object (see below). Don’t forget - this authenticator supports only JSON responses.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauthentication_data_source\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_authentication_data_source\"\u003eAuthentication Data Source\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to extract the authentication data from the request. The extracted value is made available as \u003ccode\u003eAuthenticationData\u003c/code\u003e for usage in templates defined as part of this authenticator configuration. So you can reference it in a body, header, etc.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe \u003ccode\u003eAuthenticationData\u003c/code\u003e object is available during the execution of this authenticator only and is not made available to other mechanisms.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_headers\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003eidentity_info_endpoint\u003c/code\u003e API requires any headers from the request to heimdall, you can forward these unchanged by making use of this property. This might be the header used to extract the authentication data from.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_cookies\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003eidentity_info_endpoint\u003c/code\u003e API requires any cookies from the request to heimdall, you can forward these unchanged by making use of this property. This might be the cookie used to extract the authentication data from.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epayload\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYour \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003etemplate\u003c/a\u003e with definitions required to send the extracted authentication data. The template has access to the \u003ccode\u003eAuthenticationData\u003c/code\u003e object only.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esubject\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_subject\"\u003eSubject\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to extract the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e information from the identity info endpoint response.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow long to cache the response. If not set, response caching if disabled. The cache key is calculated from the \u003ccode\u003eidentity_info_endpoint\u003c/code\u003e configuration and the actual authentication data value.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_fallback_on_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf set to \u003ccode\u003etrue\u003c/code\u003e, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esession_lifespan\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_session_lifespan\"\u003eSession Lifespan\u003c/a\u003e\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to extract the session validity information form the identity info endpoint response. If the \u003ccode\u003enot_after\u003c/code\u003e property is specified, the corresponding value from the response is also used for cache ttl calculation to prevent usage of not anymore valid session objects and overwrites the value configured for \u003ccode\u003ecache_ttl\u003c/code\u003e if the usage of that value would exceed the lifespan of the session object.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf you’re configuring the \u003ccode\u003ecache_ttl\u003c/code\u003e property, it is highly recommended to configure \u003ccode\u003esession_lifespan\u003c/code\u003e as well to ensure outdated session objects are not used for subsequent requests to heimdall. Usage of \u003ccode\u003esession_lifespan\u003c/code\u003e is recommended anyway to enable time based validation of the response from the identity info endpoint.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Configuration to work with session cookies\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example shows how to configure this authenticator to work with Ory Kratos, an authentication system, which issues a cookie upon successful user authentication to maintain the authentication state. To reduce the communication overhead, it also makes use of \u003ccode\u003ecache_ttl\u003c/code\u003e to cache the response for 5 minutes if that time frame does not exceed the actual validity of the session represented by the cookie.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekratos_session_cookie\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidentity_info_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://kratos/sessions/whoami\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_data_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ecookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eory_kratos_session\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_cookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eory_kratos_session\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eidentity.id\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003esession_lifespan\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eactive\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eactive\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissued_at\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eissued_at\u003c/span\u003e\n \u003cspan class=\"na\"\u003enot_before\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticated_at\u003c/span\u003e\n \u003cspan class=\"na\"\u003enot_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexpires_at\u003c/span\u003e\n \u003cspan class=\"na\"\u003etime_format\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e2006-01-02T15:04:05.999999Z07\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalidity_leeway\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs kratos requires the \u003ccode\u003eory_kratos_session\u003c/code\u003e cookie as is, this configuration makes use of the \u003ccode\u003eforward_cookies\u003c/code\u003e property and does not use the \u003ccode\u003eAuthenticationData\u003c/code\u003e object.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example does also show how an endpoint can be configured by just specifying the URL as string, which is the simplest way for endpoint configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Configuration to work with a Bearer token\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example shows how to configure this authenticator to work with an OAuth2 authorization service, which issues a Bearer token upon successful user authentication. To reduce the communication overhead, it also makes use of \u003ccode\u003ecache_ttl\u003c/code\u003e to cache the response for 5 minutes if it does not exceed the validity of the information present in the response from the used endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example we configure the authenticator to use the introspection endpoint to get the information about the token.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopaque_bearer_token\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidentity_info_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://my-auth.system/introspect\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eContent-Type\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapplication/x-www-form-urlencoded\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eHeimdall\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${INTROSPECTION_PASSWORD}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_data_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003etoken={{ urlenc .AuthenticationData }}\u0026amp;token_type_hint=access_token\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esub\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003esession_lifespan\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eactive\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eactive\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissued_at\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eiat\u003c/span\u003e\n \u003cspan class=\"na\"\u003enot_before\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enbf\u003c/span\u003e\n \u003cspan class=\"na\"\u003enot_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexp\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalidity_leeway\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUsually, you would not only like to verify the validity of a token, but also a couple of claims. This can be achieved by a \u003ca href=\"/docs/mechanisms/authorizers/#_local_cel\"\u003eCEL Authorizer\u003c/a\u003e. However, there is also a special purpose \u003ca href=\"#_oauth2_introspection\"\u003eOAuth2 Introspection\u003c/a\u003e authenticator type, which supports asserting all security relevant claims in just one place and does not need so much configuration as shown above.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this configuration the authenticator extracts the token from the \u003ccode\u003eAuthorization\u003c/code\u003e header and request the information about the corresponding user from the \u003ccode\u003ehttps://my-auth.system/introspect\u003c/code\u003e endpoint by sending the extracted token in the body of the request in a parameter named \u003ccode\u003etoken\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 6. Configuration to work with Google’s Firebase.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you would like to integrate with Google’s Firebase, you would configure something like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAssumption: The token issued by firebase is located in the HTTP Authorization header using Bearer scheme\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efirebase_token\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidentity_info_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${YOUR_API_KEY}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eContent-Type\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapplication/json\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_data_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{ \u0026#34;idToken\u0026#34;: {{ quote .AuthenticationData }} }\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eusers.0.localId\u003c/span\u003e\n \u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eusers.0\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_oauth2_introspection\"\u003eOAuth2 Introspection\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authenticator handles requests that have Bearer token in the HTTP Authorization header (\u003ccode\u003eAuthorization: Bearer \u0026lt;token\u0026gt;\u003c/code\u003e), in the \u003ccode\u003eaccess_token\u003c/code\u003e query parameter or the \u003ccode\u003eaccess_token\u003c/code\u003e body parameter (latter, if the body is of \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e MIME type). It then uses \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7662\"\u003eOAuth 2.0 Token Introspection\u003c/a\u003e endpoint to check if the token is valid. The validation includes at least the verification of the status and the time validity. That is if the token is still active and whether it has been issued in an acceptable time frame. Latter can be adjusted by specifying a leeway. All other validation options can and should be configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eoauth2_introspection\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eintrospection_endpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (dependant, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7662\"\u003eOAuth 2.0 Token Introspection\u003c/a\u003e endpoint of the OAuth2 authorization provider.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this property is mutually exclusive with \u003ccode\u003emetadata_endpoint\u003c/code\u003e. If used, at least the \u003ccode\u003eurl\u003c/code\u003e must be configured. There is no need to define the \u003ccode\u003emethod\u003c/code\u003e property or setting the \u003ccode\u003eContent-Type\u003c/code\u003e or the \u003ccode\u003eAccept\u003c/code\u003e header. These are set by default to the values required by the RFC referenced above. You can however override these while configuring the authenticator if needed. The path part of the \u003ccode\u003eurl\u003c/code\u003e can be \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003etemplated\u003c/a\u003e and has access to the \u003ccode\u003eTokenIssuer\u003c/code\u003e object, which is a string and only available if the format of the used token is JWT. It basically holds the value of the \u003ccode\u003eiss\u003c/code\u003e claim from the token.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emetadata_endpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (dependant, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414\"\u003eOAuth 2.0 Authorization Server Metadata\u003c/a\u003e endpoint of the OAuth2, respectively OIDC authorization provider (the \u003ca href=\"https://openid.net/specs/openid-connect-discovery-1_0.html\"\u003eOpenID Connect Discovery\u003c/a\u003e specification is an OIDC specific profile of that specification). If the token introspection URL is not known upfront, it can be resolved by making use of that endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this property is mutually exclusive with \u003ccode\u003eintrospection_endpoint\u003c/code\u003e. If used, at least the \u003ccode\u003eurl\u003c/code\u003e must be configured, can be templated and has access to the \u003ccode\u003eTokenIssuer\u003c/code\u003e object already introduced above (with the same limitations).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ccode\u003emetadata_endpoint\u003c/code\u003e is by default configured to use \u003ccode\u003eGET\u003c/code\u003e as HTTP method and sets the \u003ccode\u003eAccept\u003c/code\u003e header to \u003ccode\u003eapplication/json\u003c/code\u003e as also required by both specifications referenced above. In addition, to avoid useless communication, it is also configured to make use of HTTP cache according to \u003ca href=\"https://tools.ietf.org/html/rfc7234\"\u003eRFC 7234\u003c/a\u003e with default HTTP cache ttl set to \u003ccode\u003e30m\u003c/code\u003e. All these settings can however be overridden if required.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition to the properties specified by the \u003ca href=\"/docs/configuration/types/#_endpoint\"\u003e\u003ccode\u003eendpoint\u003c/code\u003e\u003c/a\u003e type, following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edisable_issuer_identifier_verification\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUpon retrieval of the server metadata, both, the \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414\"\u003eOAuth 2.0 Authorization Server Metadata\u003c/a\u003e RFC, and the \u003ca href=\"https://openid.net/specs/openid-connect-discovery-1_0.html\"\u003eOpenID Connect Discovery\u003c/a\u003e specification, require the verification of the issuer identifier for security reasons, e.g. to prevent \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414#section-6.2\"\u003eSpoofing Attacks\u003c/a\u003e. There are however setups, where strictly following that recommendation would result in extended bandwidth usage (instead of communicating directly with the auth server within the cluster one would need to use the same domain, the client application uses, which introduces additional network hops). It might also not work at all as the actual identifier of the issuer would change depending on where the request come from. By making use of this property and setting it to \u003ccode\u003etrue\u003c/code\u003e, one can disable the corresponding verification. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etoken_source\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_authentication_data_source\"\u003eAuthentication Data Source\u003c/a\u003e\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to get the access token from. Defaults to retrieve it from the \u003ccode\u003eAuthorization\u003c/code\u003e header, the \u003ccode\u003eaccess_token\u003c/code\u003e query parameter or the \u003ccode\u003eaccess_token\u003c/code\u003e body parameter (latter, if the body is of \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e MIME type).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eassertions\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_assertions\"\u003eAssertions\u003c/a\u003e\u003c/em\u003e (dependent, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfigures the required claim assertions. Overriding on rule level is possible even partially. Those parts of the assertion, which have not been overridden are taken from the prototype configuration. If \u003ccode\u003emetadata_endpoint\u003c/code\u003e is used, the list of issuers is optional, as the issuer will be resolved via the auth server metadata document. Otherwise, the list of issuers is mandatory.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esubject\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_subject\"\u003eSubject\u003c/a\u003e\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to extract the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e information from the introspection endpoint response. If not configured \u003ccode\u003esub\u003c/code\u003e is used to extract the subject \u003ccode\u003eID\u003c/code\u003e and all attributes from the introspection endpoint response are made available as \u003ccode\u003eAttributes\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow long to cache the response. If not set, caching of the introspection response is based on the available token expiration information. To disable caching, set it to \u003ccode\u003e0s\u003c/code\u003e. If you set the ttl to a custom value \u0026gt; 0, the expiration time (if available) of the token will be considered. The cache key is calculated from the \u003ccode\u003eintrospection_endpoint\u003c/code\u003e configuration and the value of the access token.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_fallback_on_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf set to \u003ccode\u003etrue\u003c/code\u003e, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 7. Minimal possible configuration based on the Introspection endpoint\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eat_opaque\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_introspection\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eintrospection_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://hydra:4445/oauth2/introspect\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4444/\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 8. Configuration for Keycloak utilizing metadata discovery\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emetadata_endpoint\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emetadata_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://keycloak:8080/realms/{{ trimPrefix \u0026#34;https://my-auth-server/realms/\u0026#34; .TokenIssuer }}/.well-known/openid-configuration\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# Note that no assertions are configured here, since it\u0026#39;ll be resolved via the metadata endpoint\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example does also show how to make use of templating if the format of the access token is JWT.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe external domain of the auth server in this example is \u003ccode\u003ehttps://my-auth-server.com\u003c/code\u003e.\nIf the \u003ccode\u003eiss\u003c/code\u003e claim of the issued JWT is set to \u003ccode\u003ehttps://my-auth-server.com/realms/my-app\u003c/code\u003e, the above line will build an internal URL to the metadata endpoint of the same server and profile/realm, which is that case would be \u003ccode\u003ehttps://keycloak:8080/realms/my-app/.well-known/openid-configuration\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_jwt\"\u003eJWT\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the \u003ca href=\"#_oauth2_introspection\"\u003eOAuth2 Introspection\u003c/a\u003e authenticator, this authenticator handles requests that have a Bearer token in the \u003ccode\u003eAuthorization\u003c/code\u003e header, in a different header, a query parameter or a body parameter as well. Unlike the OAuth2 Introspection authenticator it expects the token to be a JSON Web Token (JWT) and verifies it according \u003ca href=\"https://www.rfc-editor.org/rfc/rfc7519#section-7.2\"\u003eRFC 7519, Section 7.2\u003c/a\u003e. It does however not support encrypted payloads and nested JWTs. In addition to this, validation includes the verification of the time validity. Latter can be adjusted by specifying a leeway. All other validation options can and should be configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authenticator, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ejwt\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ejwks_endpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (dependant, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe JWKS endpoint, this authenticator retrieves the key material in a format specified in \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7519\"\u003eRFC 7519\u003c/a\u003e from for JWT signature verification purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this property is mutually exclusive with \u003ccode\u003emetadata_endpoint\u003c/code\u003e. If used, at least the \u003ccode\u003eurl\u003c/code\u003e must be configured. By default \u003ccode\u003emethod\u003c/code\u003e is set to \u003ccode\u003eGET\u003c/code\u003e and the HTTP \u003ccode\u003eAccept\u003c/code\u003e header to \u003ccode\u003eapplication/json\u003c/code\u003e. The path part of the \u003ccode\u003eurl\u003c/code\u003e can be \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003etemplated\u003c/a\u003e and has access to the \u003ccode\u003eTokenIssuer\u003c/code\u003e object, which is a string and basically holds the value of the \u003ccode\u003eiss\u003c/code\u003e claim from the token.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emetadata_endpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (dependant, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414\"\u003eOAuth 2.0 Authorization Server Metadata\u003c/a\u003e endpoint of the OAuth2, respectively OIDC authorization provider (the \u003ca href=\"https://openid.net/specs/openid-connect-discovery-1_0.html\"\u003eOpenID Connect Discovery\u003c/a\u003e specification is an OIDC specific profile of that specification). If the JWKS URL is not known upfront, it can be resolved by making use of that endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this property is mutually exclusive with \u003ccode\u003ejwks_endpoint\u003c/code\u003e. If used, at least the \u003ccode\u003eurl\u003c/code\u003e must be configured. As with the \u003ccode\u003ejwks_endpoint\u003c/code\u003e, the path part of the \u003ccode\u003eurl\u003c/code\u003e can be templated and has access to the \u003ccode\u003eTokenIssuer\u003c/code\u003e object already introduced above.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with the \u003ccode\u003ejwks_endpoint\u003c/code\u003e as well, the \u003ccode\u003emetadata_endpoint\u003c/code\u003e is by default configured to use \u003ccode\u003eGET\u003c/code\u003e as HTTP method and sets the \u003ccode\u003eAccept\u003c/code\u003e header to \u003ccode\u003eapplication/json\u003c/code\u003e, as also required by both specifications referenced above. In addition, to avoid useless communication, it is also configured to make use of HTTP cache according to \u003ca href=\"https://tools.ietf.org/html/rfc7234\"\u003eRFC 7234\u003c/a\u003e with default HTTP cache ttl set to \u003ccode\u003e30m\u003c/code\u003e. All these settings can however be overridden if required.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition to the properties specified by the \u003ca href=\"/docs/configuration/types/#_endpoint\"\u003e\u003ccode\u003eendpoint\u003c/code\u003e\u003c/a\u003e type, following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003edisable_issuer_identifier_verification\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eUpon retrieval of the server metadata, both, the \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414\"\u003eOAuth 2.0 Authorization Server Metadata\u003c/a\u003e RFC, and the \u003ca href=\"https://openid.net/specs/openid-connect-discovery-1_0.html\"\u003eOpenID Connect Discovery\u003c/a\u003e specification, require the verification of the issuer identifier for security reasons, e.g. to prevent \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc8414#section-6.2\"\u003eSpoofing Attacks\u003c/a\u003e. There are however setups, where strictly following that recommendation would result in extended bandwidth usage (instead of communicating directly with the auth server within the cluster one would need to use the same domain, the client application uses, which introduces additional network hops). It might also not work at all as the actual identifier of the issuer would change depending on where the request come from. By making use of this property and setting it to \u003ccode\u003etrue\u003c/code\u003e, one can disable the corresponding verification. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ejwt_source\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_authentication_data_source\"\u003eAuthentication Data Source\u003c/a\u003e\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to get the access token from. Defaults to retrieve it from the \u003ccode\u003eAuthorization\u003c/code\u003e header, the \u003ccode\u003eaccess_token\u003c/code\u003e query parameter or the \u003ccode\u003eaccess_token\u003c/code\u003e body parameter (latter, if the body is of \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e MIME type).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eassertions\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_assertions\"\u003eAssertions\u003c/a\u003e\u003c/em\u003e (dependant, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfigures the required claim assertions. Overriding on rule level is possible even partially. Those parts of the assertion, which have not been overridden are taken from the prototype configuration. If \u003ccode\u003emetadata_endpoint\u003c/code\u003e is used, the list of issuers is optional, as the issuer will be resolved via the auth server metadata document. Otherwise, the list of issuers is mandatory.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esubject\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_subject\"\u003eSubject\u003c/a\u003e\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to extract the subject id from the JWT, as well as which attributes to use. If not configured \u003ccode\u003esub\u003c/code\u003e is used to extract the subject id and all attributes from the JWT payload are made available as attributes of the subject.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow long to cache the key from the JWKS response, which was used for signature verification purposes. If not set, heimdall will cache this key for 10 minutes and not call JWKS endpoint again if the same \u003ccode\u003ekid\u003c/code\u003e is referenced in an JWT and same JWKS endpoint is used. The cache key is calculated from the \u003ccode\u003ejwks_endpoint\u003c/code\u003e configuration and the \u003ccode\u003ekid\u003c/code\u003e referenced in the JWT.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_fallback_on_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf set to \u003ccode\u003etrue\u003c/code\u003e, allows the pipeline to fall back to the next authenticator in the pipeline if this one fails to verify the credentials. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalidate_jwk\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables or disables the verification of the JWK certificate used for JWT signature verification purposes. Effective only if the JWK contains a certificate. The verification happens according to \u003ca href=\"https://www.rfc-editor.org/rfc/rfc5280#section-6.1\"\u003eRFC 5280, section 6.1\u003c/a\u003e and also includes the check, that the certificate is allowed to be used for signature verification purposes. Revocation check is not supported. Defaults to \u003ccode\u003etrue\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etrust_store\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe path to a PEM file containing the trust anchors, to be used for the JWK certificate validation. Defaults to system trust store.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf a JWT does not reference a \u003ccode\u003ekid\u003c/code\u003e, heimdall always fetches a JWKS from the configured endpoint (so no caching is done) and iterates over the received keys until one matches. If none matches, the authenticator fails.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 9. Minimal possible configuration based on the JWKS endpoint\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eat_jwt\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ejwks_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://hydra:4444/.well-known/jwks.json\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4444/\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 10. Configuration for Keycloak utilizing metadata discovery\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekeycloak\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emetadata_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://keycloak:8080/realms/my-app/.well-known/openid-configuration\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# Note that no assertions are configured here, since it\u0026#39;ll be resolved via the metadata endpoint\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Authenticators","url":"/docs/mechanisms/authenticators/"},{"categories":null,"content":" Some of the authorizers may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overriddable and partially overridable to indicate whether the property can be overridden in a rule pipeline.\nAllow As the name implies, this authorizer allows any request passing through. This authorizer type also doesn’t have any configuration options.\nTo enable the usage of this authorizer, you have to set the type property to allow.\nExample 1. Configuration of Allow authorizer id: allow_any_request type: allow Deny As the name implies, this authorizer denies any request (on HTTP response code level this is then mapped to 403 Forbidden). It basically stops the successful execution of the pipeline resulting in the execution of the error handler mechanisms. This authorizer type doesn’t have any configuration options.\nTo enable the usage of this authorizer, you have to set the type property to deny.\nExample 2. Configuration of Deny authorizer id: deny_any_request type: deny Local (CEL) This authorizer allows definition of authorization requirements based on information available about the authenticated subject, the existing pipeline results, as well as the actual request by using CEL based authorization expressions. Each expression is expected to return true to signal success. Otherwise, the authorization fails, resulting in the execution of the error handler mechanisms.\nTo enable the usage of this authorizer, you have to set the type property to cel.\nConfiguration using the config property is mandatory. Following properties are available:\nexpressions: Authorization Expression array (mandatory, overridable)\nList of authorization expressions, which define the actual authorization logic. Each expression has access to the Subject, Outputs, and the Request objects.\nExample 3. Authorization based on subject properties In this example the subject is checked to be member of the \u0026#34;admin\u0026#34; group.\nid: user_is_admin type: cel config: expressions: - expression: | has(Subject.Attributes.groups) \u0026amp;\u0026amp; Subject.Attributes.groups.exists(g, g == \u0026#34;admin\u0026#34;) message: User is not admin The first line of the expressions verifies that the property group exists. The second line checks, whether groups contains an entry named admin.\nThis example specifies also a message, which is logged, if the expression fails.\nExample 4. Authorization based on subject and request properties In this example the authorizer is configured to ensure anonymous access to a resource is possible for read requests only.\nid: no_modification_allowed_by_anonymous type: cel config: expressions: - expression: | Request.Method in [\u0026#34;GET\u0026#34;, \u0026#34;HEAD\u0026#34;, \u0026#34;OPTIONS\u0026#34;] || Subject.ID != \u0026#34;anonymous\u0026#34; message: Anonymous non-read access is forbidden The usage of this type of configuration makes sense in a pipeline, which combines multiple Authenticators, allowing anonymous and authenticated access.\nRemote This authorizer allows communication with other systems, like Open Policy Agent, Ory Keto, etc. for the actual authorization purpose. If the used endpoint answers with a not 2xx HTTP response code, this authorizer assumes, the authorization has failed, resulting in the execution of the error handler mechanisms. Otherwise, if no expressions for the verification of the response are defined, the authorizer assumes, the request has been authorized. If expressions are defined and do not fail, the authorization succeeds.\nIf your authorization system provides a payload in the response, heimdall inspects the Content-Type header to prepare the payload for further usage, e.g. for payload verification expressions, or for a Local (CEL) authorizer. If the content type does either end with json or is application/x-www-form-urlencoded, the payload is decoded, so key based access to the corresponding attributes is possible, otherwise it is made available as well, but as a simple string. In all cases this value is available for the authorization expressions, as well as in the Outputs property under a key named by the id of the authorizer (See also the example below).\nTo enable the usage of this authorizer, you have to set the type property to remote.\nConfiguration using the config property is mandatory. Following properties are available:\nendpoint: Endpoint (mandatory, not overridable)\nThe API endpoint of your authorization system. At least the url must be configured. This mechanism allows templating of the url and makes the Subject object, the Outputs object, as well as the Values (see also below) objects available to it. By default, this authorizer will use HTTP POST to send the rendered payload to this endpoint. You can override this behavior by configuring method as well. Depending on the API requirements of your authorization system, you might need to configure further properties, like headers, etc.\npayload: string (optional, overridable)\nYour template with definitions required to communicate to the authorization endpoint. The template can make use of Values, Outputs, Subject and Request objects.\nexpressions: Authorization Expression array (optional, overridable)\nList of CEL expressions which define the logic to be applied to the response returned by the endpoint. All expressions are expected to evaluate to true if the authorization was successful. If any of the expressions evaluates to false, the authorization fails and the message defined by the failed expression will be logged.\nEach expression has access to the Payload object.\nforward_response_headers_to_upstream: string array (optional, overridable)\nEnables forwarding of any headers from the authorization endpoint response to the upstream service.\ncache_ttl: Duration (optional, overridable)\nAllows caching of the authorization endpoint responses. Defaults to 0s, which means no caching. The cache key is calculated from the entire configuration of the authorizer instance and the available information about the current subject.\nvalues map of strings (optional, overridable)\nA key value map, which is made accessible to the template rendering engine as Values object, to render parts of the URL and/or the payload. The actual values in that map can be templated as well with access to the Subject, the Outputs, and Request objects.\nExample 5. Configuration of Remote authorizer to communicate with Open Policy Agent (OPA) Here the remote authorizer is configured to communicate with OPA. Since OPA expects the query to be formatted as JSON, the corresponding Content-Type header is set. Since the responses are JSON objects as well, the Accept header is also provided. In addition, this examples uses the basic_auth auth type to authenticate against the endpoint.\nid: opa type: remote config: endpoint: url: https://opa.local/v1/data/{{ .Values.namespace }}/{{ .Values.policy }} headers: Content-Type: json Accept: json auth: type: basic_auth config: user: ${OPA_USER} password: ${OPA_PASSWORD} payload: | { \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }} }, \u0026#34;some_data\u0026#34;: {{ quote .Values.whatever }}, \u0026#34;more_data\u0026#34;: {{ quote .Outputs.whatever }} } values: namespace: myapi/policy policy: allow_write whatever: | {{ .Request.Header(\u0026#34;X-Whatever\u0026#34;) }} expressions: - expression: | Payload.result == true message: User does not have required permissions In this case, since an OPA response could look like { \u0026#34;result\u0026#34;: true } or { \u0026#34;result\u0026#34;: false }, heimdall makes the response also available under Outputs[\u0026#34;opa\u0026#34;], with \u0026#34;opa\u0026#34; being the id of the authorizer in this example.\nA specific rule could then use this authorizer in the following ways:\n- id: rule1 # other rule properties execute: - # other mechanisms - authorizer: opa # using defaults - # other mechanisms - id: rule2 # other rule properties execute: - # other mechanisms - authorizer: opa config: # overriding with rule specifics values: policy: allow_read whatever: | {{ .Request.Header(\u0026#34;X-SomethingElse\u0026#34;) }} - # other mechanisms ","description":"Authorizers ensure that only those subjects, which are eligible can access the desired resource. This page describes the available authorizer types in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome of the authorizers may support or require additional configuration. The corresponding properties are annotated with \u003ccode\u003emandatory\u003c/code\u003e, respectively \u003ccode\u003eoptional\u003c/code\u003e to denote configuration requirement, as well as with \u003ccode\u003eoverridable\u003c/code\u003e, \u003ccode\u003enot overriddable\u003c/code\u003e and \u003ccode\u003epartially overridable\u003c/code\u003e to indicate whether the property can be overridden in a rule pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_allow\"\u003eAllow\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this authorizer allows any request passing through. This authorizer type also doesn’t have any configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authorizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eallow\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Configuration of Allow authorizer\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow_any_request\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_deny\"\u003eDeny\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this authorizer denies any request (on HTTP response code level this is then mapped to \u003ccode\u003e403 Forbidden\u003c/code\u003e). It basically stops the successful execution of the pipeline resulting in the execution of the error handler mechanisms. This authorizer type doesn’t have any configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authorizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003edeny\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Configuration of Deny authorizer\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_any_request\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_local_cel\"\u003eLocal (CEL)\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authorizer allows definition of authorization requirements based on information available about the authenticated subject, the existing pipeline results, as well as the actual request by using \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e based authorization expressions. Each expression is expected to return \u003ccode\u003etrue\u003c/code\u003e to signal success. Otherwise, the authorization fails, resulting in the execution of the error handler mechanisms.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authorizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ecel\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexpressions\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_authorization_expression\"\u003eAuthorization Expression\u003c/a\u003e array\u003c/em\u003e (mandatory, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eList of authorization expressions, which define the actual authorization logic. Each expression has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e, and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Authorization based on subject properties\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example the subject is checked to be member of the \u0026#34;admin\u0026#34; group.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003euser_is_admin\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ehas(Subject.Attributes.groups) \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eSubject.Attributes.groups.exists(g, g == \u0026#34;admin\u0026#34;)\u003c/span\u003e\n \u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eUser is not admin\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe first line of the expressions verifies that the property group exists. The second line checks, whether \u003ccode\u003egroups\u003c/code\u003e contains an entry named \u003ccode\u003eadmin\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example specifies also a message, which is logged, if the expression fails.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Authorization based on subject and request properties\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example the authorizer is configured to ensure anonymous access to a resource is possible for read requests only.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eno_modification_allowed_by_anonymous\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eRequest.Method in [\u0026#34;GET\u0026#34;, \u0026#34;HEAD\u0026#34;, \u0026#34;OPTIONS\u0026#34;] || Subject.ID != \u0026#34;anonymous\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAnonymous non-read access is forbidden\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe usage of this type of configuration makes sense in a pipeline, which combines multiple \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eAuthenticators\u003c/a\u003e, allowing anonymous and authenticated access.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_remote\"\u003eRemote\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis authorizer allows communication with other systems, like \u003ca href=\"https://www.openpolicyagent.org/\"\u003eOpen Policy Agent\u003c/a\u003e, \u003ca href=\"https://www.ory.sh/docs/keto/\"\u003eOry Keto\u003c/a\u003e, etc. for the actual authorization purpose. If the used endpoint answers with a not 2xx HTTP response code, this authorizer assumes, the authorization has failed, resulting in the execution of the error handler mechanisms. Otherwise, if no expressions for the verification of the response are defined, the authorizer assumes, the request has been authorized. If expressions are defined and do not fail, the authorization succeeds.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf your authorization system provides a payload in the response, heimdall inspects the \u003ccode\u003eContent-Type\u003c/code\u003e header to prepare the payload for further usage, e.g. for payload verification expressions, or for a \u003ca href=\"#_local_cel\"\u003eLocal (CEL)\u003c/a\u003e authorizer. If the content type does either end with \u003ccode\u003ejson\u003c/code\u003e or is \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e, the payload is decoded, so key based access to the corresponding attributes is possible, otherwise it is made available as well, but as a simple string. In all cases this value is available for the authorization expressions, as well as in the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e property under a key named by the \u003ccode\u003eid\u003c/code\u003e of the authorizer (See also the example below).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this authorizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eremote\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eendpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe API endpoint of your authorization system. At least the \u003ccode\u003eurl\u003c/code\u003e must be configured. This mechanism allows templating of the url and makes the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e object, the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e object, as well as the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e (see also below) objects available to it. By default, this authorizer will use HTTP \u003ccode\u003ePOST\u003c/code\u003e to send the rendered payload to this endpoint. You can override this behavior by configuring \u003ccode\u003emethod\u003c/code\u003e as well. Depending on the API requirements of your authorization system, you might need to configure further properties, like headers, etc.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epayload\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYour \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003etemplate\u003c/a\u003e with definitions required to communicate to the authorization endpoint. The template can make use of \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexpressions\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_authorization_expression\"\u003eAuthorization Expression\u003c/a\u003e array\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eList of \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e expressions which define the logic to be applied to the response returned by the endpoint. All expressions are expected to evaluate to \u003ccode\u003etrue\u003c/code\u003e if the authorization was successful. If any of the expressions evaluates to \u003ccode\u003efalse\u003c/code\u003e, the authorization fails and the message defined by the failed expression will be logged.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach expression has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_payload\"\u003e\u003ccode\u003ePayload\u003c/code\u003e\u003c/a\u003e object.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_response_headers_to_upstream\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables forwarding of any headers from the authorization endpoint response to the upstream service.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAllows caching of the authorization endpoint responses. Defaults to 0s, which means no caching. The cache key is calculated from the entire configuration of the authorizer instance and the available information about the current subject.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalues\u003c/code\u003e\u003c/strong\u003e \u003cem\u003emap of strings\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA key value map, which is made accessible to the template rendering engine as \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e object, to render parts of the URL and/or the payload. The actual values in that map can be templated as well with access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e, the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e, and \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Configuration of Remote authorizer to communicate with \u003ca href=\"https://www.openpolicyagent.org/\"\u003eOpen Policy Agent\u003c/a\u003e (OPA)\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere the remote authorizer is configured to communicate with OPA. Since OPA expects the query to be formatted as JSON, the corresponding \u003ccode\u003eContent-Type\u003c/code\u003e header is set. Since the responses are JSON objects as well, the \u003ccode\u003eAccept\u003c/code\u003e header is also provided. In addition, this examples uses the \u003ccode\u003ebasic_auth\u003c/code\u003e auth type to authenticate against the endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopa\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://opa.local/v1/data/{{ .Values.namespace }}/{{ .Values.policy }}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eContent-Type\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejson\u003c/span\u003e\n \u003cspan class=\"na\"\u003eAccept\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejson\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${OPA_USER}\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${OPA_PASSWORD}\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{ \u0026#34;input\u0026#34;: { \u0026#34;user\u0026#34;: {{ quote .Subject.ID }} }, \u0026#34;some_data\u0026#34;: {{ quote .Values.whatever }}, \u0026#34;more_data\u0026#34;: {{ quote .Outputs.whatever }} }\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003enamespace\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emyapi/policy\u003c/span\u003e\n \u003cspan class=\"na\"\u003epolicy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow_write\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewhatever\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ .Request.Header(\u0026#34;X-Whatever\u0026#34;) }}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.result == true\u003c/span\u003e\n \u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eUser does not have required permissions\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this case, since an OPA response could look like \u003ccode\u003e{ \u0026#34;result\u0026#34;: true }\u003c/code\u003e or \u003ccode\u003e{ \u0026#34;result\u0026#34;: false }\u003c/code\u003e, heimdall makes the response also available under \u003ccode\u003eOutputs[\u0026#34;opa\u0026#34;]\u003c/code\u003e, with \u003ccode\u003e\u0026#34;opa\u0026#34;\u003c/code\u003e being the id of the authorizer in this example.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA specific rule could then use this authorizer in the following ways:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule1\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other rule properties\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopa\u003c/span\u003e \u003cspan class=\"c1\"\u003e# using defaults\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\n\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule2\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other rule properties\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopa\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"c1\"\u003e# overriding with rule specifics\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epolicy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow_read\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewhatever\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ .Request.Header(\u0026#34;X-SomethingElse\u0026#34;) }}\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Authorizers","url":"/docs/mechanisms/authorizers/"},{"categories":null,"content":" Some of the contextualizers may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overriddable and partially overridable to indicate whether the property can be overridden in a rule pipeline.\nGeneric This mechanism allows you to communicate to any API you want to fetch further information about the subject. Typical scenario is getting specific attributes for later authorization purposes which are not known to the authentication system and thus were not made available in Subject’s Attributes property. If the API responses with a 2xx HTTP response code, the payload is made available in the Outputs object, otherwise, if not overridden, an error is thrown and the execution of the authentication \u0026amp; authorization pipeline stops. To avoid overwriting of existing key value pairs, this object is however not available on the top level, but under a key named by the id of the contextualizer (See also the example below). If the Content-Type of the response is either ending with json or is application/x-www-form-urlencoded, the payload is decoded and made available as map, otherwise it is treated as string, but, as written above, is made available as well.\nTo enable the usage of this contextualizer, you have to set the type property to generic.\nConfiguration using the config property is mandatory. Following properties are available:\nendpoint: Endpoint (mandatory, not overridable)\nThe API of the service providing additional attributes about the authenticated user. At least the url must be configured. This mechanism allows templating of the url and makes the Subject, the Outputs object, as well as the Values (see also below) objects available to it. By default, this contextualizer will use HTTP POST to send the rendered payload to this endpoint. You can override this behavior by configuring method as well. Depending on the API requirements of the system, this contextualizer should communicate to, you might need to configure further properties, like headers, etc.\nforward_headers: string array (optional, overridable)\nIf the API requires any headers from the request to heimdall, you can forward these unchanged by making use of this property\nforward_cookies: string array (optional, overridable)\nIf the API requires any cookies from the request to heimdall, you can forward these unchanged by making use of this property.\npayload: string (optional, overridable)\nYour template with definitions required to communicate to the endpoint. The template can make use of Values, Subject, the Outputs, and Request objects.\ncache_ttl: Duration (optional, overridable)\nAllows caching of the API responses. Defaults to 10 seconds. The cache key is calculated from the entire configuration of the contextualizer instance and the available information about the current subject.\ncontinue_pipeline_on_error: boolean (optional, overridable)\nIf set to true, allows the pipeline to continue with the execution of the next mechanisms. So the error, if thrown, is ignored. Defaults to false, which means the execution of the authentication \u0026amp; authorization pipeline is stopped and the execution of the error pipeline is started.\nvalues map of strings (optional, overridable)\nA key value map, which is made accessible to the template rendering engine as Values object to render parts of the URL and/or the payload. The actual values in that map can be templated as well with access to the Subject, the Outputs and Request objects.\nExample 1. Contextualizer configuration without payload In this example the contextualizer is configured to call an endpoint using the HTTP GET method with the subject id being part of the url path. As the endpoint requires the X-My-Session-Cookie cookie for subject authentication purposes, forward_cookies is used to achieve this.\nid: foo type: generic config: endpoint: url: https://some-other.service/users/{{.Subject.ID}} method: GET forward_cookies: - X-My-Session-Cookie Example 2. Contextualizer configuration with payload In this example the contextualizer is configured to call an endpoint using the HTTP POST and send some data.\nid: foo type: generic config: endpoint: url: https://some-other.service/users method: POST payload: | { \u0026#34;user_id\u0026#34;: {{ quote .Values.user_id }} \u0026#34;whatever\u0026#34;: {{ quote .Outputs.whatever }} } Since the values property is not defined but used in the payload, it must be specified in a rule making use of this contextualzer, e.g. in the following way:\n- id: rule1 # other rule properties execute: - # other mechanisms - contextualizer: foo config: # overriding with rule specifics values: user_id: \u0026#34;{{ .Subject.ID }}\u0026#34; - # other mechanisms ","description":"Contextualizers allow you enriching the information about the request and the authenticated subject. This page describes the available contextualizer types in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome of the contextualizers may support or require additional configuration. The corresponding properties are annotated with \u003ccode\u003emandatory\u003c/code\u003e, respectively \u003ccode\u003eoptional\u003c/code\u003e to denote configuration requirement, as well as with \u003ccode\u003eoverridable\u003c/code\u003e, \u003ccode\u003enot overriddable\u003c/code\u003e and \u003ccode\u003epartially overridable\u003c/code\u003e to indicate whether the property can be overridden in a rule pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_generic\"\u003eGeneric\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis mechanism allows you to communicate to any API you want to fetch further information about the subject. Typical scenario is getting specific attributes for later authorization purposes which are not known to the authentication system and thus were not made available in \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject’s\u003c/code\u003e\u003c/a\u003e \u003ccode\u003eAttributes\u003c/code\u003e property. If the API responses with a 2xx HTTP response code, the payload is made available in the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e object, otherwise, if not overridden, an error is thrown and the execution of the authentication \u0026amp; authorization pipeline stops. To avoid overwriting of existing key value pairs, this object is however not available on the top level, but under a key named by the \u003ccode\u003eid\u003c/code\u003e of the contextualizer (See also the example below). If the \u003ccode\u003eContent-Type\u003c/code\u003e of the response is either ending with \u003ccode\u003ejson\u003c/code\u003e or is \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e, the payload is decoded and made available as map, otherwise it is treated as string, but, as written above, is made available as well.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this contextualizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003egeneric\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eendpoint\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe API of the service providing additional attributes about the authenticated user. At least the \u003ccode\u003eurl\u003c/code\u003e must be configured. This mechanism allows templating of the url and makes the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e, the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e object, as well as the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e (see also below) objects available to it. By default, this contextualizer will use HTTP \u003ccode\u003ePOST\u003c/code\u003e to send the rendered payload to this endpoint. You can override this behavior by configuring \u003ccode\u003emethod\u003c/code\u003e as well. Depending on the API requirements of the system, this contextualizer should communicate to, you might need to configure further properties, like headers, etc.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_headers\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the API requires any headers from the request to heimdall, you can forward these unchanged by making use of this property\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_cookies\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the API requires any cookies from the request to heimdall, you can forward these unchanged by making use of this property.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epayload\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eYour \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003etemplate\u003c/a\u003e with definitions required to communicate to the endpoint. The template can make use of \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e, the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e, and \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAllows caching of the API responses. Defaults to 10 seconds. The cache key is calculated from the entire configuration of the contextualizer instance and the available information about the current subject.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003econtinue_pipeline_on_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf set to \u003ccode\u003etrue\u003c/code\u003e, allows the pipeline to continue with the execution of the next mechanisms. So the error, if thrown, is ignored. Defaults to \u003ccode\u003efalse\u003c/code\u003e, which means the execution of the authentication \u0026amp; authorization pipeline is stopped and the execution of the error pipeline is started.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalues\u003c/code\u003e\u003c/strong\u003e \u003cem\u003emap of strings\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA key value map, which is made accessible to the template rendering engine as \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e object to render parts of the URL and/or the payload. The actual values in that map can be templated as well with access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e, the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Contextualizer configuration without payload\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example the contextualizer is configured to call an endpoint using the HTTP \u003ccode\u003eGET\u003c/code\u003e method with the subject id being part of the url path. As the endpoint requires the \u003ccode\u003eX-My-Session-Cookie\u003c/code\u003e cookie for subject authentication purposes, \u003ccode\u003eforward_cookies\u003c/code\u003e is used to achieve this.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://some-other.service/users/{{.Subject.ID}}\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_cookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eX-My-Session-Cookie\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Contextualizer configuration with payload\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example the contextualizer is configured to call an endpoint using the HTTP \u003ccode\u003ePOST\u003c/code\u003e and send some data.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://some-other.service/users\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ePOST\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;user_id\u0026#34;: {{ quote .Values.user_id }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;whatever\u0026#34;: {{ quote .Outputs.whatever }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince the \u003ccode\u003evalues\u003c/code\u003e property is not defined but used in the payload, it must be specified in a rule making use of this contextualzer, e.g. in the following way:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule1\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# other rule properties\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"c1\"\u003e# overriding with rule specifics\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# other mechanisms\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Contextualizers","url":"/docs/mechanisms/contextualizers/"},{"categories":null,"content":" Some finalizers may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overriddable and partially overridable to indicate whether the property can be overridden in a rule pipeline.\nNoop As the name implies, this finalizer does nothing. This finalizer type also doesn’t have any configuration options.\nTo enable the usage of this finalizer, you have to set the type property to noop.\nExample 1. Noop finalizer configuration id: foo type: noop Header This finalizer enables transformation of a Subject and the Outputs objects into HTTP headers. It can also be used to map information from the original Request into headers expected by the upstream service.\nTo enable the usage of this finalizer, you have to set the type property to header.\nConfiguration using the config property is mandatory. Following properties are available:\nheaders: string map (mandatory, overridable)\nEnables configuration of arbitrary headers with any values build from available information (See also Templating).\nExample 2. Header finalizer configuration id: foo type: header config: headers: X-User-ID: \u0026#39;{{ quote .Subject.ID }}\u0026#39; X-User-Email: \u0026#39;{{ index .Subject.Attributes \u0026#34;email\u0026#34; | quote }}\u0026#39; Host: \u0026#39;{{ .Request.Header \u0026#34;Host\u0026#34; | quote }}\u0026#39; Cookie This finalizer enables transformation of a Subject and the Outputs objects into cookies. It can also be used to map information from the original Request into cookies expected by the upstream service.\nTo enable the usage of this finalizer, you have to set the type property to cookie.\nConfiguration using the config property is mandatory. Following properties are available:\ncookies: string map (mandatory, overridable)\nEnables configuration of arbitrary cookies with any values build from available information (See also Templating).\nExample 3. Cookie finalizer configuration id: foo type: cookies config: cookies: user_id_cookie: \u0026#39;{{ quote .Subject.ID }}\u0026#39; user_email_cookie: \u0026#39;{{ index .Subject.Attributes \u0026#34;email\u0026#34; | quote }}\u0026#39; JWT This finalizer enables transformation of the Subject and the Outputs objects into custom claims within a JWT. The resulting token is then made available to your upstream service in either the HTTP Authorization header (using the Bearer scheme) or in a custom header. Your upstream service can verify the JWT’s signature using heimdall’s JWKS endpoint to retrieve the necessary public keys/certificates.\nTo enable this finalizer, set the type property to jwt.\nConfiguration using the config property is mandatory. The following properties are available:\nsigner: Signer (mandatory, not overridable)\nDefines the key material for signing the JWT, as well as the iss claim.\nclaims: string (optional, overridable)\nA template specifying custom claims for the JWT. The template can use Values, Outputs, and Subject objects.\nvalues: map of strings (optional, overridable)\nA key-value map accessible as Values in the template engine for rendering claims. Values in this map can also be templated with access to Subject and Outputs.\nttl: Duration (optional, overridable)\nDefines the JWT’s validity period. Defaults to 5 minutes. Heimdall automatically sets the iat and nbf claims to the current system time, and exp is calculated based on the ttl value.\nheader: object (optional, not overridable)\nSpecifies the HTTP header name and optional scheme for passing the JWT. Defaults to Authorization with scheme Bearer. If defined, name is required, and if scheme is omitted, the JWT is set as a raw value.\nThe generated JWT is cached until 5 seconds before expiration. The cache key is computed based on the finalizer’s configuration, the Subject, and the Outputs attributes.\nExample 4. JWT finalizer configuration id: jwt_finalizer type: jwt config: ttl: 5m header: name: X-Token claims: | { {{ $user_name := .Subject.Attributes.identity.user_name -}} \u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.identity.email }}, \u0026#34;email_verified\u0026#34;: {{ .Subject.Attributes.identity.email_verified }}, \u0026#34;name\u0026#34;: {{ if $user_name }}{{ quote $user_name }}{{ else }}{{ quote $email }}{{ end }}, \u0026#34;extra\u0026#34;: {{ .Values | toJson }} } In a rule that references the jwt_finalizer, additional claims can be dynamically inserted into the \u0026#34;extra\u0026#34; claim without redefining claims:\n- id: some_rule # Other rule properties execute: - # Other mechanisms - finalizer: jwt_finalizer config: values: foo: bar user_id: \u0026#39;{{ .Subject.ID }}\u0026#39; - # Other mechanisms OAuth2 Client Credentials This finalizer drives the OAuth2 Client Credentials Grant flow to obtain a token, which should be used for communication with the upstream service. By default, as long as not otherwise configured (see the options below), the obtained token is made available to your upstream service in the HTTP Authorization header with Bearer scheme set. Unlike the other finalizers, it does not have access to any objects created by the rule execution pipeline.\nTo enable the usage of this finalizer, you have to set the type property to oauth2_client_credentials.\nConfiguration using the config property is mandatory. Following properties are available:\ntoken_url: string (mandatory, not overridable)\nThe token endpoint of the authorization server.\nclient_id: string (mandatory, not overridable)\nThe client identifier for heimdall.\nclient_secret: string (mandatory, not overridable)\nThe client secret for heimdall.\nauth_method: string (optional, not overridable)\nThe authentication method to be used according to RFC 6749, Client Password. Can be one of\nbasic_auth (default if auth_method is not set): With that authentication method, the \u0026#34;application/x-www-form-urlencoded\u0026#34; encoded values of client_id and client_secret are sent to the authorization server via the Authorization header using the Basic scheme.\nrequest_body: With that authentication method the client_id and client_secret are sent in the request body together with the other parameters (e.g. scopes) defined by the flow.\nUsage of request_body authentication method is not recommended and should be avoided. scopes: string array (optional, overridable)\nThe scopes required for the access token.\ncache_ttl: Duration (optional, overridable)\nHow long to cache the token received from the token endpoint. Defaults to the token expiration information from the token endpoint (the value of the expires_in field) if present. If the token expiration inforation is not present and cache_ttl is not configured, the received token is not cached. If the token expiration information is present in the response and cache_ttl is configured the shorter value is taken. If caching is enabled, the token is cached until 5 seconds before its expiration. To disable caching, set it to 0s. The cache key calculation is based on the entire oauth2_client_credentials configuration without considering the header property.\nheader: object (optional, overridable)\nDefines the name and scheme to be used for the header. Defaults to Authorization with scheme Bearer. If defined, the name property must be set. If scheme is not defined, no scheme will be prepended to the resulting JWT.\nExample 5. OAuth2 Client Credentials finalizer configuration id: get_token type: oauth2_client_credentials config: cache_ttl: 5m header: name: X-Token scheme: MyScheme token_url: https://my-oauth-provider.com/token client_id: my_client client_secret: VerySecret! auth_method: basic_auth scopes: - foo - bar ","description":"Finalizers are the last steps executed in a rule pipeline and can e.g. create a special representation of the subject to be made available to the upstream service. This page describes the available finalizer types in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome finalizers may support or require additional configuration. The corresponding properties are annotated with \u003ccode\u003emandatory\u003c/code\u003e, respectively \u003ccode\u003eoptional\u003c/code\u003e to denote configuration requirement, as well as with \u003ccode\u003eoverridable\u003c/code\u003e, \u003ccode\u003enot overriddable\u003c/code\u003e and \u003ccode\u003epartially overridable\u003c/code\u003e to indicate whether the property can be overridden in a rule pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_noop\"\u003eNoop\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs the name implies, this finalizer does nothing. This finalizer type also doesn’t have any configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this finalizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003enoop\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Noop finalizer configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003enoop\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_header\"\u003eHeader\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis finalizer enables transformation of a \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e objects into HTTP headers. It can also be used to map information from the original \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e into headers expected by the upstream service.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this finalizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eheader\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheaders\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring map\u003c/em\u003e (mandatory, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables configuration of arbitrary headers with any values build from available information (See also \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003eTemplating\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Header finalizer configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eX-User-ID\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eX-User-Email\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eindex\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.Attributes\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e|\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eHost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Request.Header\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;Host\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e|\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cookie\"\u003eCookie\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis finalizer enables transformation of a \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e objects into cookies. It can also be used to map information from the original \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e into cookies expected by the upstream service.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this finalizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ecookie\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecookies\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring map\u003c/em\u003e (mandatory, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables configuration of arbitrary cookies with any values build from available information (See also \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003eTemplating\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Cookie finalizer configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecookies\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser_id_cookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser_email_cookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eindex\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.Attributes\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e|\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_jwt\"\u003eJWT\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis finalizer enables transformation of the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e objects into custom claims within a \u003ca href=\"https://www.rfc-editor.org/rfc/rfc7519\"\u003eJWT\u003c/a\u003e. The resulting token is then made available to your upstream service in either the HTTP \u003ccode\u003eAuthorization\u003c/code\u003e header (using the \u003ccode\u003eBearer\u003c/code\u003e scheme) or in a custom header. Your upstream service can verify the JWT’s signature using heimdall’s JWKS endpoint to retrieve the necessary public keys/certificates.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable this finalizer, set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ejwt\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. The following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esigner\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_signer\"\u003eSigner\u003c/a\u003e\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines the key material for signing the JWT, as well as the \u003ccode\u003eiss\u003c/code\u003e claim.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclaims\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"/docs/mechanisms/evaluation_objects/#_templating\"\u003etemplate\u003c/a\u003e specifying custom claims for the JWT. The template can use \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e, \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e, and \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalues\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emap of strings\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA key-value map accessible as \u003ca href=\"/docs/mechanisms/evaluation_objects/#_values\"\u003e\u003ccode\u003eValues\u003c/code\u003e\u003c/a\u003e in the template engine for rendering claims. Values in this map can also be templated with access to \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ettl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines the JWT’s validity period. Defaults to 5 minutes. Heimdall automatically sets the \u003ccode\u003eiat\u003c/code\u003e and \u003ccode\u003enbf\u003c/code\u003e claims to the current system time, and \u003ccode\u003eexp\u003c/code\u003e is calculated based on the \u003ccode\u003ettl\u003c/code\u003e value.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheader\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eobject\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies the HTTP header \u003ccode\u003ename\u003c/code\u003e and optional \u003ccode\u003escheme\u003c/code\u003e for passing the JWT. Defaults to \u003ccode\u003eAuthorization\u003c/code\u003e with scheme \u003ccode\u003eBearer\u003c/code\u003e. If defined, \u003ccode\u003ename\u003c/code\u003e is required, and if \u003ccode\u003escheme\u003c/code\u003e is omitted, the JWT is set as a raw value.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe generated JWT is cached until 5 seconds before expiration. The cache key is computed based on the finalizer’s configuration, the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e, and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_outputs\"\u003e\u003ccode\u003eOutputs\u003c/code\u003e\u003c/a\u003e attributes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. JWT finalizer configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_finalizer\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclaims\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{{ $user_name := .Subject.Attributes.identity.user_name -}}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;email\u0026#34;: {{ quote .Subject.Attributes.identity.email }},\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;email_verified\u0026#34;: {{ .Subject.Attributes.identity.email_verified }},\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;name\u0026#34;: {{ if $user_name }}{{ quote $user_name }}{{ else }}{{ quote $email }}{{ end }},\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;extra\u0026#34;: {{ .Values | toJson }}\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn a rule that references the \u003ccode\u003ejwt_finalizer\u003c/code\u003e, additional claims can be dynamically inserted into the \u003ccode\u003e\u0026#34;extra\u0026#34;\u003c/code\u003e claim without redefining \u003ccode\u003eclaims\u003c/code\u003e:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esome_rule\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# Other rule properties\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# Other mechanisms\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_finalizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efoo\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"c1\"\u003e# Other mechanisms\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_oauth2_client_credentials\"\u003eOAuth2 Client Credentials\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis finalizer drives the \u003ca href=\"https://www.rfc-editor.org/rfc/rfc6749#section-4.4\"\u003eOAuth2 Client Credentials Grant\u003c/a\u003e flow to obtain a token, which should be used for communication with the upstream service. By default, as long as not otherwise configured (see the options below), the obtained token is made available to your upstream service in the HTTP \u003ccode\u003eAuthorization\u003c/code\u003e header with \u003ccode\u003eBearer\u003c/code\u003e scheme set. Unlike the other finalizers, it does not have access to any objects created by the rule execution pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this finalizer, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eoauth2_client_credentials\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration using the \u003ccode\u003econfig\u003c/code\u003e property is mandatory. Following properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etoken_url\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe token endpoint of the authorization server.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclient_id\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe client identifier for heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclient_secret\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe client secret for heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauth_method\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe authentication method to be used according to \u003ca href=\"https://www.rfc-editor.org/rfc/rfc6749#section-2.3.1\"\u003eRFC 6749, Client Password\u003c/a\u003e. Can be one of\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ebasic_auth\u003c/code\u003e (default if \u003ccode\u003eauth_method\u003c/code\u003e is not set): With that authentication method, the \u003ccode\u003e\u0026#34;application/x-www-form-urlencoded\u0026#34;\u003c/code\u003e encoded values of \u003ccode\u003eclient_id\u003c/code\u003e and \u003ccode\u003eclient_secret\u003c/code\u003e are sent to the authorization server via the \u003ccode\u003eAuthorization\u003c/code\u003e header using the \u003ccode\u003eBasic\u003c/code\u003e scheme.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003erequest_body\u003c/code\u003e: With that authentication method the \u003ccode\u003eclient_id\u003c/code\u003e and \u003ccode\u003eclient_secret\u003c/code\u003e are sent in the request body together with the other parameters (e.g. \u003ccode\u003escopes\u003c/code\u003e) defined by the flow.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsage of \u003ccode\u003erequest_body\u003c/code\u003e authentication method is not recommended and should be avoided.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escopes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe scopes required for the access token.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow long to cache the token received from the token endpoint. Defaults to the token expiration information from the token endpoint (the value of the \u003ccode\u003eexpires_in\u003c/code\u003e field) if present. If the token expiration inforation is not present and \u003ccode\u003ecache_ttl\u003c/code\u003e is not configured, the received token is not cached. If the token expiration information is present in the response and \u003ccode\u003ecache_ttl\u003c/code\u003e is configured the shorter value is taken. If caching is enabled, the token is cached until 5 seconds before its expiration. To disable caching, set it to \u003ccode\u003e0s\u003c/code\u003e. The cache key calculation is based on the entire \u003ccode\u003eoauth2_client_credentials\u003c/code\u003e configuration without considering the \u003ccode\u003eheader\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheader\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eobject\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines the \u003ccode\u003ename\u003c/code\u003e and \u003ccode\u003escheme\u003c/code\u003e to be used for the header. Defaults to \u003ccode\u003eAuthorization\u003c/code\u003e with scheme \u003ccode\u003eBearer\u003c/code\u003e. If defined, the \u003ccode\u003ename\u003c/code\u003e property must be set. If \u003ccode\u003escheme\u003c/code\u003e is not defined, no scheme will be prepended to the resulting JWT.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. OAuth2 Client Credentials finalizer configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eget_token\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_client_credentials\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Token\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eMyScheme\u003c/span\u003e\n \u003cspan class=\"na\"\u003etoken_url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://my-oauth-provider.com/token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy_client\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_secret\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecret!\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_method\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Finalizers","url":"/docs/mechanisms/finalizers/"},{"categories":null,"content":" Some of the error handlers may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overriddable and partially overridable to indicate whether the property can be overridden in a rule pipeline.\nDefault This error handler is always there and is executed if no other error handler mechanism is responsible for the error. Actually, there is no need to explicitly configure it. The only exception is to allow overriding the default rule’s error handler chain in a specific rule for performance reasons (if configured error handlers in the default rule should not be considered). This mechanism type doesn’t have any configuration options.\nTo enable the usage of this mechanism, you have to set the type property to default.\nExample 1. Configuring Default error handler to enable referencing it from rules id: foo type: default Redirect This error handler mechanism allows redirecting the client to another endpoint, e.g. to let the user authenticate. Technically this error handler returns e.g. a HTTP 302 Found response code and sets the HTTP Location header.\nTo enable the usage of this mechanism, you have to set the type property to redirect.\nConfiguration is mandatory by making use of the config property supporting the following settings:\nto: URL (mandatory, not overridable)\nThe url to redirect the client to via the Location header. Can be templated and has access to the Request object.\nWhen creating query parameters by making use of templates, don’t forget to encode the values using the urlenc function. See also examples below. code: int (optional, not overridable)\nThe code to be used for the redirect. Defaults to 302 Found.\nHeimdall does not check the configured code for HTTP redirect validity! Example 2. Redirect error handler configuration The redirect error handler below is configured to kick in if the error is either authentication_error or authorization_error and the request come from a browser (HTTP Accept header contains text/html). If this condition holds true it will redirect the client to https://127.0.0.1:4433/self-service/login/browser and add the return_to query parameter set to the URL encoded value of the current url as well.\nSo, e.g. if heimdall was handling the request for https://my-service.local/foo and run into an error like described above, the HTTP response to the client will have the code 302 Found set and the Location header set to https://127.0.0.1:4433/self-service/login/browser?return_to=https%3A%2F%2Fmy-service.local%2Ffoo\nid: authenticate_with_kratos type: redirect config: to: https://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }} WWW-Authenticate This error handler mechanism responds with HTTP 401 Unauthorized and a WWW-Authenticate HTTP header set. As of now, this error handler is the only one error handler, which transforms heimdall into an authentication system, a very simple one though. By configuring this error handler you can implement the Basic HTTP Authentication Scheme by also making use of the Basic Auth authenticator. Without that authenticator, the usage of this error handler does actually not make any sense.\nTo enable the usage of this error handler, you have to set the type property to www_authenticate.\nConfiguration is mandatory by making use of the if and config properties. The first defines the condition, which must hold true for this error handler to execute and has access to the Request and the Error objects. Latter defines the data to drive the redirect and supports the following properties:\nrealm: string (optional, overridable)\nThe \u0026#34;realm\u0026#34; according to RFC 7235, section 2.2. Defaults to \u0026#34;Please authenticate\u0026#34;.\nExample 3. Configuration of WWW-Authenticate error handler The www authenticate error handler below is configured to kick in if an authentication_error error occurred (an error raised by authenticators) and has been raised by an authenticator with id equal to basic_auth_authenticator. In this case, it will respond with HTTP 401 Unauthorized and a WWW-Authenticate header set to Basic realm=\u0026#34;My fancy app\u0026#34;.\nid: basic_authenticate type: www_authenticate if: | Error.Source == \u0026#34;basic_auth_authenticator\u0026#34; \u0026amp;\u0026amp; type(Error) == authentication_error config: realm: \u0026#34;My fancy app\u0026#34; ","description":"Error handlers kick in when any of the stages of the regular rule pipeline fail and let you define logic to handle such situations. This page describes the available error handler types in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSome of the error handlers may support or require additional configuration. The corresponding properties are annotated with \u003ccode\u003emandatory\u003c/code\u003e, respectively \u003ccode\u003eoptional\u003c/code\u003e to denote configuration requirement, as well as with \u003ccode\u003eoverridable\u003c/code\u003e, \u003ccode\u003enot overriddable\u003c/code\u003e and \u003ccode\u003epartially overridable\u003c/code\u003e to indicate whether the property can be overridden in a rule pipeline.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_default\"\u003eDefault\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis error handler is always there and is executed if no other error handler mechanism is responsible for the error. Actually, there is no need to explicitly configure it. The only exception is to allow overriding the \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule’s\u003c/a\u003e error handler chain in a specific rule for performance reasons (if configured error handlers in the default rule should not be considered). This mechanism type doesn’t have any configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this mechanism, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003edefault\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Configuring Default error handler to enable referencing it from rules\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_redirect\"\u003eRedirect\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis error handler mechanism allows redirecting the client to another endpoint, e.g. to let the user authenticate. Technically this error handler returns e.g. a HTTP \u003ccode\u003e302 Found\u003c/code\u003e response code and sets the HTTP \u003ccode\u003eLocation\u003c/code\u003e header.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this mechanism, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003eredirect\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration is mandatory by making use of the \u003ccode\u003econfig\u003c/code\u003e property supporting the following settings:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eto\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eURL\u003c/em\u003e (mandatory, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe url to redirect the client to via the \u003ccode\u003eLocation\u003c/code\u003e header. Can be templated and has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e object.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nWhen creating query parameters by making use of templates, don’t forget to encode the values using the \u003ccode\u003eurlenc\u003c/code\u003e function. See also examples below.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecode\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eint\u003c/em\u003e (optional, not overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe code to be used for the redirect. Defaults to \u003ccode\u003e302 Found\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nHeimdall does not check the configured code for HTTP redirect validity!\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Redirect error handler configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe redirect error handler below is configured to kick in if the error is either \u003ccode\u003eauthentication_error\u003c/code\u003e or \u003ccode\u003eauthorization_error\u003c/code\u003e and the request come from a browser (HTTP \u003ccode\u003eAccept\u003c/code\u003e header contains \u003ccode\u003etext/html\u003c/code\u003e). If this condition holds true it will redirect the client to \u003ccode\u003ehttps://127.0.0.1:4433/self-service/login/browser\u003c/code\u003e and add the \u003ccode\u003ereturn_to\u003c/code\u003e query parameter set to the URL encoded value of the current url as well.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSo, e.g. if heimdall was handling the request for \u003ccode\u003ehttps://my-service.local/foo\u003c/code\u003e and run into an error like described above, the HTTP response to the client will have the code \u003ccode\u003e302 Found\u003c/code\u003e set and the \u003ccode\u003eLocation\u003c/code\u003e header set to \u003ccode\u003ehttps://127.0.0.1:4433/self-service/login/browser?return_to=https%3A%2F%2Fmy-service.local%2Ffoo\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticate_with_kratos\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_www_authenticate\"\u003eWWW-Authenticate\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis error handler mechanism responds with HTTP \u003ccode\u003e401 Unauthorized\u003c/code\u003e and a \u003ccode\u003eWWW-Authenticate\u003c/code\u003e HTTP header set. As of now, this error handler is the only one error handler, which transforms heimdall into an authentication system, a very simple one though. By configuring this error handler you can implement the \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7617\"\u003eBasic HTTP Authentication Scheme\u003c/a\u003e by also making use of the \u003ca href=\"/docs/mechanisms/authenticators/#_basic_auth\"\u003eBasic Auth\u003c/a\u003e authenticator. Without that authenticator, the usage of this error handler does actually not make any sense.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable the usage of this error handler, you have to set the \u003ccode\u003etype\u003c/code\u003e property to \u003ccode\u003ewww_authenticate\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eConfiguration is mandatory by making use of the \u003ccode\u003eif\u003c/code\u003e and \u003ccode\u003econfig\u003c/code\u003e properties. The first defines the condition, which must hold true for this error handler to execute and has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_error\"\u003e\u003ccode\u003eError\u003c/code\u003e\u003c/a\u003e objects. Latter defines the data to drive the redirect and supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003erealm\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u0026#34;realm\u0026#34; according to \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7235#section-2.2\"\u003eRFC 7235, section 2.2\u003c/a\u003e. Defaults to \u0026#34;Please authenticate\u0026#34;.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Configuration of WWW-Authenticate error handler\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe www authenticate error handler below is configured to kick in if an \u003ccode\u003eauthentication_error\u003c/code\u003e error occurred (an error raised by authenticators) and has been raised by an authenticator with id equal to \u003ccode\u003ebasic_auth_authenticator\u003c/code\u003e. In this case, it will respond with HTTP \u003ccode\u003e401 Unauthorized\u003c/code\u003e and a \u003ccode\u003eWWW-Authenticate\u003c/code\u003e header set to \u003ccode\u003eBasic realm=\u0026#34;My fancy app\u0026#34;\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_authenticate\u003c/span\u003e\n\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ewww_authenticate\u003c/span\u003e\n\u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003eError.Source == \u0026#34;basic_auth_authenticator\u0026#34; \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) == authentication_error\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003erealm\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eMy\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003efancy\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eapp\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Mechanisms"],"tags":null,"title":"Error Handlers","url":"/docs/mechanisms/error_handlers/"},{"categories":null,"content":" In the simplest case, a regular rule reuses mechanisms from the previously defined catalogue in its pipelines. In more complex scenarios, a rule can reconfigure parts of the mechanisms being used. The specific parts that can be reconfigured or overridden depend on the mechanism itself and are described in the mechanism-specific documentation. Reconfiguration is always limited to the particular rule’s pipeline and does not affect other rules.\nConfiguration A single regular rule consists of the following properties:\nid: string (mandatory)\nThe unique identifier of the rule. It must be unique across all rules loaded by the same Rule Provider. To ensure uniqueness, it’s recommended to include the upstream service’s name and the rule’s purpose in the id. For example, rule:my-service:public-api.\nmatch: RuleMatcher (mandatory)\nDefines the matching criteria for a rule, with the following properties:\nroutes: RouteMatcher array (mandatory)\nSpecifies route conditions for matching the rule to incoming HTTP requests with each entry having the following properties:\npath: string (mandatory)\nThe Path Expression describing the request path this rule should match. It supports both simple and free (named) wildcards.\npath_params: PathParameterConditions (optional)\nAdditional conditions for the values captured by named wildcards in the path expression. Each entry supports the following properties:\nname: string (mandatory)\nThe name of the wildcard.\ntype: string (mandatory)\nThe type of expression used to match the captured wildcard’s value. The supported types are:\nglob: to use a glob expression to match the captured value (/ is used as a delimiter, so * matches anything until the next /).\nregex to use a regular expression to match the captured value.\nvalue: string (mandatory)\nThe actual expression based on the given type.\nbacktracking_enabled: boolean (optional)\nEnables or disables backtracking when a request matches the path expressions but fails to meet additional matching criteria, like path_params, hosts, etc. This setting is inherited from the default rule and defaults to that rule’s setting. When enabled, the system will backtrack to attempt a match with a less specific rule (see Rule Matching Specificity \u0026amp; Backtracking for more details).\nhosts: HostMatcher array (optional)\nDefines a set of hosts to match against the HTTP Host header. Each entry has the following properties:\ntype: string (mandatory)\nSpecifies the type of expression for matching the host, which can be one of:\nexact to match the host exactly\nglob to use a glob expression which should be satisfied by the host of the incoming request (. is used as a delimiter, which means * will match anything until the next .).\nregex to use a regular expression which should be satisfied by the host of the incoming request.\nvalue: string (mandatory)\nThe actual host expression based on the type.\nscheme: string (optional)\nThe expected HTTP scheme. If not specified, both http and https are accepted.\nmethods: string array (optional)\nSpecifies the allowed HTTP methods (GET, POST, PATCH, etc). If not specified, all methods are allowed. To allow all methods except specific ones, use ALL and prefix the methods to exclude with !. For example:\n# Methods list which effectively expands to all HTTP methods methods: - ALL # Methods list consisting of all HTTP methods without `TRACE` and `OPTIONS` methods: - ALL - \u0026#34;!TRACE\u0026#34; - \u0026#34;!OPTIONS\u0026#34; allow_encoded_slashes: string (optional)\nControls how to handle URL-encoded slashes in request paths during matching and forwarding. Options include:\noff - Reject requests with encoded slashes (%2F). This is the default behavior.\non - Accept requests with encoded slashes decoding them to /.\nno_decode - Accept requests with encoded slashes without touching them.\nHandling URL-encoded slashes may differ across the proxies in front of heimdall, heimdall, and the upstream service. Accepting requests with encoded slashes could, depending on your rules, lead to Interpretation Conflict vulnerabilities resulting in privilege escalations. forward_to: RequestForwarder (mandatory in Proxy operation mode)\nSpecifies where to forward proxied requests when heimdall is operating in proxy mode. The following properties are supported:\nhost: string (mandatory)\nHost (and port) for forwarding the request. If no rewrite property (see below) is defined, the original URL’s scheme, path, and other components are preserved. E.g. if the original request is https://mydomain.com/api/v1/something?foo=bar\u0026amp;bar=baz and the value of this property is set to my-backend:8080, the url used to forward the request to the upstream will be https://my-backend:8080/api/v1/something?foo=bar\u0026amp;bar=baz\nThe Host header is not preserved when forwarding the request. To preserve it, use of the header finalizer in your execute pipeline and set it accordingly. The example below demonstrates that. rewrite: OriginalURLRewriter (optional)\nCan be used to rewrite further parts of the original URL before forwarding the request. If specified, at least one of the following supported (middleware) properties must be specified:\nscheme: string (optional)\nSpecifies the URL scheme to use when forwarding the request. Defaults to the scheme used in the original request.\nUnless heimdall is started with the --insecure-skip-upstream-tls-enforcement flag, only https is allowed as the scheme. strip_path_prefix: string (optional)\nThis middleware strips the specified prefix from the original URL path before forwarding. E.g. if the path of the original url is /api/v1/something and the value of this property is set to /api/v1, the request to the upstream will have the url path set to /something.\nadd_path_prefix: string (optional)\nThis middleware is applied after the execution of the strip_path_prefix middleware described above. If specified, heimdall will add the specified path prefix to the path used to forward the request to the upstream service. E.g. if the path of the original URL or the path resulting after the application of the strip_path_prefix middleware is /something and the value of this property is set to /my-backend, the request to the upstream will have the URL path set to /my-backend/something.\nstrip_query_parameters: string array (optional)\nRemoves specified query parameters from the original URL before forwarding. E.g. if the query parameters part of the original URL is foo=bar\u0026amp;bar=baz and the value of this property is set to [\u0026#34;foo\u0026#34;], the query part of the request to the upstream will be set to bar=baz\nexecute: Authentication \u0026amp; Authorization Pipeline (mandatory)\nSpecifies the mechanisms used for authentication, authorization, contextualization, and finalization.\non_error: Error Pipeline (optional)\nSpecifies error handling mechanisms if the pipeline defined by the execute property fails. Defaults to the error pipeline defined in the default rule if not specified.\nExample 1. An example rule id: rule:foo:bar match: routes: - path: /some/:identifier/followed/by/** path_params: - name: identifier type: glob value: \u0026#34;[a-z]\u0026#34; scheme: https hosts: - type: exact value: my-service.local methods: - GET - POST forward_to: host: backend-a:8080 rewrite: scheme: https strip_path_prefix: /api/v1 execute: # the following just demonstrates how to make use of specific # mechanisms in the simplest possible form - authenticator: foo - authorizer: bar - contextualizer: foo - finalizer: zab # the following one demonstrates how to preserve the # Host header from the original request, while forwarding # it to the upstream service - finalizer: preserve-host # the config property can be omitted, if already configured # in the header finalizer mechanism config: headers: Host: \u0026#39;{{ .Request.Header \u0026#34;Host\u0026#34; | quote }}\u0026#39; on_error: - error_handler: foobar Path Expression Path expressions are used to match the incoming requests. When specifying these, you can make use of two types of wildcards:\nfree wildcard, which can be defined using * and\nsingle wildcard, which can be defined using :\nBoth can be named and unnamed, with named wildcards allowing accessing of the matched segments in the pipeline of the rule using the defined name as a key on the Request.URL.Captures object. Unnamed free wildcard is defined as ** and unnamed single wildcard is defined as :*. A named wildcard uses some identifier instead of the *, so like *name for free wildcard and :name for single wildcard.\nThe value of the path segment, respectively path segments available via the wildcard name is decoded. E.g. if you define the to be matched path in a rule as /file/:name, and the actual path of the request is /file/%5Bid%5D, you’ll get [id] when accessing the captured path segment via the name key. Not every path encoded value is decoded though. Decoding of encoded slashes happens only if allow_encoded_slashes was set to on.\nThere are some simple rules, which must be followed while using wildcards:\nOne can use as many single wildcards, as needed in any segment\nA segment must start with : or * to define a wildcard\nNo segments are allowed after a free (named) wildcard\nIf a regular segment must start with : or *, but should not be considered as a wildcard, it must be escaped with \\.\nHere some path examples:\n/apples/and/bananas - Matches exactly the given path\n/apples/and/:something - Matches /apples/and/bananas, /apples/and/oranges and alike, but not /apples/and/bananas/andmore or /apples/or/bananas. Since a named single wildcard is used, the actual value of the path segment matched by :something can be accessed in the rule pipeline using something as a key.\n/apples/:junction/:something - Similar to above. But will also match /apples/or/bananas in addition to /apples/and/bananas and /apples/and/oranges.\n/apples/and/some:thing - Matches exactly /apples/and/some:thing\n/apples/and/some** - Matches exactly /apples/and/some**\n/apples/** - Matches any path starting with /apples/, like /apples/and/bananas but not /apples/.\n/apples/*remainingpath - Same as above, but uses a named free wildcard\n/apples/**/bananas - Is invalid, as there is a path segment after a free wildcard\n/apples/\\*remainingpath - Matches exactly /apples/*remainingpath\nHere is an example demonstrating the usage of a single named wildcard:\nid: rule:1 match: routes: - path: /files/:uuid/delete hosts: - type: exact value: hosty.mchostface execute: - authorizer: openfga_check config: payload: | { \u0026#34;user\u0026#34;: \u0026#34;{{ .Subject.ID }}\u0026#34;, \u0026#34;relation\u0026#34;: \u0026#34;can_delete\u0026#34;, \u0026#34;object\u0026#34;: \u0026#34;file:{{ .Request.URL.Captures.uuid }}\u0026#34; } Rule Matching Specificity \u0026amp; Backtracking The implementation ensures that rules with more specific path expressions are matched first, regardless of their placement within a rule set. In fact, more specific rules are prioritized even when they are defined across different rule sets.\nWhen a path expression matches a request, any additional conditions specified in the rule’s matching criteria are evaluated. Only if these conditions are met will the rule’s pipeline be executed.\nIf multiple rules share the same path expression and all their additional conditions match, the first matching rule will be applied. The matching order is determined by the sequence of rules in the rule set. If no rule is matched, and backtracking is enabled, the process will backtrack to attempt a match with the next less specific rule. Backtracking will stop when:\na less specific rule successfully matches (including evaluation of any additional conditions), or\na less specific rule fails to match and does not permit backtracking.\nThe following examples illustrate these principles:\nImagine the following set of rules\nid: rule1 match: routes: - path: /files/** execute: - \u0026lt;pipeline definition\u0026gt; id: rule2 match: routes: - path: /files/:team/:name path_params: - name: team type: regex value: \u0026#34;(team1|team2)\u0026#34; backtracking_enabled: true execute: - \u0026lt;pipeline definition\u0026gt; id: rule3 match: routes: - path: /files/team3/:name execute: - \u0026lt;pipeline definition\u0026gt; The request to /files/team1/document.pdf will be matched by rule2, as it is more specific than rule1. Consequently, the pipeline for rule2 will be executed.\nThe request to /files/team3/document.pdf will be matched by rule3, which is more specific than both rule1 and rule2. As a result, the corresponding pipeline will be executed.\nHowever, even though the request to /files/team4/document.pdf matches the path defined in rule2, the regular expression (team1|team2) used in the path_params for the team parameter will not match. Since backtracking_enabled is set to true, backtracking will occur, and the request will be matched by rule1, with its pipeline then being executed.\nAuthentication \u0026amp; Authorization Pipeline As described in the Concepts section, this pipeline consists of mechanisms, previously configured in the mechanisms catalogue, organized in stages as described below, with authentication stage (consisting of authenticators) being mandatory.\nAuthentication Stage: List of authenticator references using authenticator as key, followed by the required authenticator id. Authenticators following the first defined in the list are used by heimdall as fallback. That is, if first authenticator fails due to missing authentication data, second is executed, etc. By default, fallback is not used if an authenticator fails due to validation errors of the given authentication data. E.g. if an authenticator fails to validate the signature of a JWT token, the next authenticator in the list will not be executed. Instead, the entire pipeline will fail and lead to the execution of the error pipeline. This list is mandatory if no default rule is configured.\nSome authenticators use the same sources to get subject authentication object from. E.g. the jwt and the oauth2_introspection authenticators can retrieve tokens from the same places in the request. If such authenticators are used in the same pipeline, you should configure the more specific ones before the more general ones to have working default fallbacks. To stay with the above example, the jwt authenticator is more specific compared to oauth2_introspection, as it will be only executed, if the token is in a JWT format. In contrast to this, the oauth2_introspection authenticator is more general and does not care about the token format, thus will feel responsible for the request as soon as it finds a bearer token. You can however also make use of the allow_fallback_on_error configuration property and set it to true. This will allow a fallback even if the verification of the credentials fail. Authorization Stage: List of contextualizer and authorizer references in any order (optional). Can also be mixed. As with authenticators, the list definition happens using either contextualizer or authorizer as key, followed by the required id. All mechanisms in this list are executed in the order, they are defined. If any of these fails, the entire pipeline fails, which leads to the execution of the error pipeline. This list is optional.\nFinalization Stage: List of finalizer references using finalizers as key, followed by the required finalizer id. All finalizers in this list are executed in the order they are defined. If any of these fail, the entire pipeline fails, which leads to the execution of the error pipeline. This list is optional. If a default rule is configured, and no finalizers are configured on a specific rule level, the finalizers from the default rule are used. If the default rule does not have any finalizers configured either, no finalization will take place.\nIn all cases, the used mechanism can be partially reconfigured if supported by the corresponding type. Configuration goes into the config properties. These reconfigurations are always local to the given rule. With other words, you can adjust your rule specific pipeline as you want without any side effects.\nExecution of an contextualizer, authorizer, or finalizer mechanisms can optionally happen conditionally by making use of a CEL expression in an if clause, which has access to the Subject and the Request objects. If the if clause is not present, the corresponding mechanism is always executed.\nExample 2. Complex pipeline # list of authenticators # defining the authentication stage - authenticator: foo - authenticator: bar config: subject: anon # ... any further required authenticator # list of authorizers and contextualizers in any order # defining the authentication stage - contextualizer: baz config: cache_ttl: 0s - authorizer: zab - contextualizer: foo if: Subject.ID != \u0026#34;anonymous\u0026#34; - contextualizer: bar - authorizer: foo if: Request.Method == \u0026#34;POST\u0026#34; config: expressions: - expression: | // some expression logic deviating from the // definition in the pipeline configuration. # ... any further required authorizer or contextualizer # list of finalizers # defining the finalization stage - finalizer: foo - finalizer: bar config: headers: - X-User-ID: {{ quote .ID }} # ... any further required finalizers This example uses\ntwo authenticators, with authenticator named bar being the fallback for the authenticator named foo. This fallback authenticator is obviously of type anonymous as it reconfigures the referenced prototype to use anon for subject id.\nmultiple contextualizers and authorizers, with first contextualizer having its cache disabled (cache_ttl set to 0s) and the last authorizer being of type cel as it reconfigures the referenced prototype to use a different authorization expression.\ntwo finalizers, with the second one being obviously of type header, as it defines a X-User-ID header set to the value of the subject id to be forwarded to the upstream service.\ncontextualizer foo is only executed if the authenticated subject is not anonymous.\nauthorizer foo is only executed if the request method is HTTP POST.\nError Pipeline Compared to the Authentication \u0026amp; Authorization Pipeline, the error pipeline is pretty simple. It is also a list of mechanism references, but all referenced types are error handler types. Thus, each entry in this list must have error_handler as key, followed by the ìd of the required error handler previously defined in the mechanism catalogue.\nExecution of the error handlers should happen conditionally by making use of a CEL expression in an if clause, which has access to the Error and the Request objects. Otherwise, the first error handler will be executed and the error pipeline will exit.\nAs with the authentication \u0026amp; authorization pipeline, partial reconfiguration of the used mechanisms is possible if supported by the corresponding type. The overrides are always local to the given rule as well.\nExample 3. Two error handlers - error_handler: foo if: # rule specific condition - error_handler: bar config: # rule specific config This example uses two error handlers, named foo and bar. bar will only be executed if foo \u0026#39;s error condition does not match. bar does also override the error handler configuration as required by the given rule.\n","description":"Regular rules allow definition and as such execution of arbitrary logic required by your upstream service. This page describes the available configuration options for a regular rule in detail.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn the simplest case, a regular rule reuses mechanisms from the previously defined \u003ca href=\"/docs/mechanisms/catalogue/\"\u003ecatalogue\u003c/a\u003e in its pipelines. In more complex scenarios, a rule can reconfigure parts of the mechanisms being used. The specific parts that can be reconfigured or overridden depend on the mechanism itself and are described in the mechanism-specific documentation. Reconfiguration is always limited to the particular rule’s pipeline and does not affect other rules.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration\"\u003eConfiguration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA single regular rule consists of the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eid\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe unique identifier of the rule. It must be unique across all rules loaded by the same \u003ca href=\"/docs/rules/providers/\"\u003eRule Provider\u003c/a\u003e. To ensure uniqueness, it’s recommended to include the upstream service’s name and the rule’s purpose in the id. For example, \u003ccode\u003erule:my-service:public-api\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ematch\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eRuleMatcher\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines the matching criteria for a rule, with the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eroutes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eRouteMatcher array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies route conditions for matching the rule to incoming HTTP requests with each entry having the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epath\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ca href=\"#_path_expression\"\u003ePath Expression\u003c/a\u003e describing the request path this rule should match. It supports both simple and free (named) wildcards.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epath_params\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003ePathParameterConditions\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAdditional conditions for the values captured by named wildcards in the path expression. Each entry supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the wildcard.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etype\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe type of expression used to match the captured wildcard’s value. The supported types are:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eglob\u003c/code\u003e: to use a \u003ca href=\"https://github.com/gobwas/glob\"\u003eglob expression\u003c/a\u003e to match the captured value (\u003ccode\u003e/\u003c/code\u003e is used as a delimiter, so \u003ccode\u003e*\u003c/code\u003e matches anything until the next \u003ccode\u003e/\u003c/code\u003e).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eregex\u003c/code\u003e to use a regular expression to match the captured value.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalue\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual expression based on the given \u003ccode\u003etype\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebacktracking_enabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables or disables backtracking when a request matches the path expressions but fails to meet additional matching criteria, like \u003ccode\u003epath_params\u003c/code\u003e, \u003ccode\u003ehosts\u003c/code\u003e, etc. This setting is inherited from the default rule and defaults to that rule’s setting. When enabled, the system will backtrack to attempt a match with a less specific rule (see \u003ca href=\"#_rule_matching_specificity_backtracking\"\u003eRule Matching Specificity \u0026amp; Backtracking\u003c/a\u003e for more details).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehosts\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eHostMatcher array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines a set of hosts to match against the HTTP Host header. Each entry has the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etype\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies the type of expression for matching the host, which can be one of:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eexact\u003c/code\u003e to match the host exactly\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eglob\u003c/code\u003e to use a \u003ca href=\"https://github.com/gobwas/glob\"\u003eglob expression\u003c/a\u003e which should be satisfied by the host of the incoming request (\u003ccode\u003e.\u003c/code\u003e is used as a delimiter, which means \u003ccode\u003e*\u003c/code\u003e will match anything until the next \u003ccode\u003e.\u003c/code\u003e).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eregex\u003c/code\u003e to use a regular expression which should be satisfied by the host of the incoming request.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalue\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual host expression based on the \u003ccode\u003etype\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escheme\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe expected HTTP scheme. If not specified, both http and https are accepted.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emethods\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies the allowed HTTP methods (\u003ccode\u003eGET\u003c/code\u003e, \u003ccode\u003ePOST\u003c/code\u003e, \u003ccode\u003ePATCH\u003c/code\u003e, etc). If not specified, all methods are allowed. To allow all methods except specific ones, use \u003ccode\u003eALL\u003c/code\u003e and prefix the methods to exclude with \u003ccode\u003e!\u003c/code\u003e. For example:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# Methods list which effectively expands to all HTTP methods\u003c/span\u003e\n\u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eALL\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# Methods list consisting of all HTTP methods without `TRACE` and `OPTIONS`\u003c/span\u003e\n\u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eALL\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e!TRACE\u0026#34;\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e!OPTIONS\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_encoded_slashes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eControls how to handle URL-encoded slashes in request paths during matching and forwarding. Options include:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eoff\u003c/code\u003e\u003c/strong\u003e - Reject requests with encoded slashes (\u003ccode\u003e%2F\u003c/code\u003e). This is the default behavior.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eon\u003c/code\u003e\u003c/strong\u003e - Accept requests with encoded slashes decoding them to \u003ccode\u003e/\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eno_decode\u003c/code\u003e\u003c/strong\u003e - Accept requests with encoded slashes without touching them.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nHandling URL-encoded slashes may differ across the proxies in front of heimdall, heimdall, and the upstream service. Accepting requests with encoded slashes could, depending on your rules, lead to \u003ca href=\"https://cwe.mitre.org/data/definitions/436.html\"\u003eInterpretation Conflict\u003c/a\u003e vulnerabilities resulting in privilege escalations.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eforward_to\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eRequestForwarder\u003c/em\u003e (mandatory in Proxy operation mode)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies where to forward proxied requests when heimdall is operating in proxy mode. The following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehost\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHost (and port) for forwarding the request. If no \u003ccode\u003erewrite\u003c/code\u003e property (see below) is defined, the original URL’s scheme, path, and other components are preserved. E.g. if the original request is \u003ccode\u003ehttps://mydomain.com/api/v1/something?foo=bar\u0026amp;bar=baz\u003c/code\u003e and the value of this property is set to \u003ccode\u003emy-backend:8080\u003c/code\u003e, the url used to forward the request to the upstream will be \u003ccode\u003ehttps://my-backend:8080/api/v1/something?foo=bar\u0026amp;bar=baz\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe \u003ccode\u003eHost\u003c/code\u003e header is not preserved when forwarding the request. To preserve it, use of the \u003ca href=\"/docs/mechanisms/finalizers/#_header\"\u003eheader finalizer\u003c/a\u003e in your \u003ccode\u003eexecute\u003c/code\u003e pipeline and set it accordingly. The example below demonstrates that.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003erewrite\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eOriginalURLRewriter\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCan be used to rewrite further parts of the original URL before forwarding the request. If specified, at least one of the following supported (middleware) properties must be specified:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escheme\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies the URL scheme to use when forwarding the request. Defaults to the scheme used in the original request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUnless heimdall is started with the \u003ccode\u003e--insecure-skip-upstream-tls-enforcement\u003c/code\u003e flag, only \u003ccode\u003ehttps\u003c/code\u003e is allowed as the scheme.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003estrip_path_prefix\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis middleware strips the specified prefix from the original URL path before forwarding. E.g. if the path of the original url is \u003ccode\u003e/api/v1/something\u003c/code\u003e and the value of this property is set to \u003ccode\u003e/api/v1\u003c/code\u003e, the request to the upstream will have the url path set to \u003ccode\u003e/something\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eadd_path_prefix\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis middleware is applied after the execution of the \u003ccode\u003estrip_path_prefix\u003c/code\u003e middleware described above. If specified, heimdall will add the specified path prefix to the path used to forward the request to the upstream service. E.g. if the path of the original URL or the path resulting after the application of the \u003ccode\u003estrip_path_prefix\u003c/code\u003e middleware is \u003ccode\u003e/something\u003c/code\u003e and the value of this property is set to \u003ccode\u003e/my-backend\u003c/code\u003e, the request to the upstream will have the URL path set to \u003ccode\u003e/my-backend/something\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003estrip_query_parameters\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRemoves specified query parameters from the original URL before forwarding. E.g. if the query parameters part of the original URL is \u003ccode\u003efoo=bar\u0026amp;bar=baz\u003c/code\u003e and the value of this property is set to \u003ccode\u003e[\u0026#34;foo\u0026#34;]\u003c/code\u003e, the query part of the request to the upstream will be set to \u003ccode\u003ebar=baz\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexecute\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies the mechanisms used for authentication, authorization, contextualization, and finalization.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eon_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_error_pipeline\"\u003eError Pipeline\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies error handling mechanisms if the pipeline defined by the \u003ccode\u003eexecute\u003c/code\u003e property fails. Defaults to the error pipeline defined in the \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e if not specified.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. An example rule\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:foo:bar\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/some/:identifier/followed/by/**\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath_params\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eidentifier\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eglob\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e[a-z]\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-service.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePOST\u003c/span\u003e\n\u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebackend-a:8080\u003c/span\u003e\n \u003cspan class=\"na\"\u003erewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps\u003c/span\u003e\n \u003cspan class=\"na\"\u003estrip_path_prefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/api/v1\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# the following just demonstrates how to make use of specific\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# mechanisms in the simplest possible form\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ezab\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# the following one demonstrates how to preserve the\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# Host header from the original request, while forwarding\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# it to the upstream service\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003epreserve-host\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# the config property can be omitted, if already configured\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# in the header finalizer mechanism\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eHost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Request.Header\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;Host\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e|\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\n\u003cspan class=\"na\"\u003eon_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_path_expression\"\u003ePath Expression\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ePath expressions are used to match the incoming requests. When specifying these, you can make use of two types of wildcards:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003efree wildcard, which can be defined using \u003ccode\u003e*\u003c/code\u003e and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003esingle wildcard, which can be defined using \u003ccode\u003e:\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBoth can be named and unnamed, with named wildcards allowing accessing of the matched segments in the pipeline of the rule using the defined name as a key on the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_url_captures\"\u003e\u003ccode\u003eRequest.URL.Captures\u003c/code\u003e\u003c/a\u003e object. Unnamed free wildcard is defined as \u003ccode\u003e**\u003c/code\u003e and unnamed single wildcard is defined as \u003ccode\u003e:*\u003c/code\u003e. A named wildcard uses some identifier instead of the \u003ccode\u003e*\u003c/code\u003e, so like \u003ccode\u003e*name\u003c/code\u003e for free wildcard and \u003ccode\u003e:name\u003c/code\u003e for single wildcard.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe value of the path segment, respectively path segments available via the wildcard name is decoded. E.g. if you define the to be matched path in a rule as \u003ccode\u003e/file/:name\u003c/code\u003e, and the actual path of the request is \u003ccode\u003e/file/%5Bid%5D\u003c/code\u003e, you’ll get \u003ccode\u003e[id]\u003c/code\u003e when accessing the captured path segment via the \u003ccode\u003ename\u003c/code\u003e key. Not every path encoded value is decoded though. Decoding of encoded slashes happens only if \u003ccode\u003eallow_encoded_slashes\u003c/code\u003e was set to \u003ccode\u003eon\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThere are some simple rules, which must be followed while using wildcards:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eOne can use as many single wildcards, as needed in any segment\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eA segment must start with \u003ccode\u003e:\u003c/code\u003e or \u003ccode\u003e*\u003c/code\u003e to define a wildcard\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eNo segments are allowed after a free (named) wildcard\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIf a regular segment must start with \u003ccode\u003e:\u003c/code\u003e or \u003ccode\u003e*\u003c/code\u003e, but should not be considered as a wildcard, it must be escaped with \u003ccode\u003e\\\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere some path examples:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/and/bananas\u003c/code\u003e - Matches exactly the given path\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/and/:something\u003c/code\u003e - Matches \u003ccode\u003e/apples/and/bananas\u003c/code\u003e, \u003ccode\u003e/apples/and/oranges\u003c/code\u003e and alike, but not \u003ccode\u003e/apples/and/bananas/andmore\u003c/code\u003e or \u003ccode\u003e/apples/or/bananas\u003c/code\u003e. Since a named single wildcard is used, the actual value of the path segment matched by \u003ccode\u003e:something\u003c/code\u003e can be accessed in the rule pipeline using \u003ccode\u003esomething\u003c/code\u003e as a key.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/:junction/:something\u003c/code\u003e - Similar to above. But will also match \u003ccode\u003e/apples/or/bananas\u003c/code\u003e in addition to \u003ccode\u003e/apples/and/bananas\u003c/code\u003e and \u003ccode\u003e/apples/and/oranges\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/and/some:thing\u003c/code\u003e - Matches exactly \u003ccode\u003e/apples/and/some:thing\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/and/some**\u003c/code\u003e - Matches exactly \u003ccode\u003e/apples/and/some**\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/**\u003c/code\u003e - Matches any path starting with \u003ccode\u003e/apples/\u003c/code\u003e, like \u003ccode\u003e/apples/and/bananas\u003c/code\u003e but not \u003ccode\u003e/apples/\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/*remainingpath\u003c/code\u003e - Same as above, but uses a named free wildcard\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/**/bananas\u003c/code\u003e - Is invalid, as there is a path segment after a free wildcard\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e/apples/\\*remainingpath\u003c/code\u003e - Matches exactly \u003ccode\u003e/apples/*remainingpath\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere is an example demonstrating the usage of a single named wildcard:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/files/:uuid/delete\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehosty.mchostface\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopenfga_check\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e{\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;user\u0026#34;: \u0026#34;{{ .Subject.ID }}\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;relation\u0026#34;: \u0026#34;can_delete\u0026#34;,\u003c/span\u003e\n \u003cspan class=\"s\"\u003e\u0026#34;object\u0026#34;: \u0026#34;file:{{ .Request.URL.Captures.uuid }}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"s\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_rule_matching_specificity_backtracking\"\u003eRule Matching Specificity \u0026amp; Backtracking\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe implementation ensures that rules with more specific path expressions are matched first, regardless of their placement within a rule set. In fact, more specific rules are prioritized even when they are defined across different rule sets.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhen a path expression matches a request, any additional conditions specified in the rule’s matching criteria are evaluated. Only if these conditions are met will the rule’s pipeline be executed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf multiple rules share the same path expression and all their additional conditions match, the first matching rule will be applied. The matching order is determined by the sequence of rules in the rule set.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf no rule is matched, and backtracking is enabled, the process will backtrack to attempt a match with the next less specific rule. Backtracking will stop when:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ea less specific rule successfully matches (including evaluation of any additional conditions), or\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ea less specific rule fails to match and does not permit backtracking.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following examples illustrate these principles:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine the following set of rules\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule1\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/files/**\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;pipeline definition\u0026gt;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule2\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/files/:team/:name\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath_params\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eteam\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eregex\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e(team1|team2)\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebacktracking_enabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;pipeline definition\u0026gt;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule3\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/files/team3/:name\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e\u0026lt;pipeline definition\u0026gt;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe request to \u003ccode\u003e/files/team1/document.pdf\u003c/code\u003e will be matched by \u003ccode\u003erule2\u003c/code\u003e, as it is more specific than \u003ccode\u003erule1\u003c/code\u003e. Consequently, the pipeline for \u003ccode\u003erule2\u003c/code\u003e will be executed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe request to \u003ccode\u003e/files/team3/document.pdf\u003c/code\u003e will be matched by \u003ccode\u003erule3\u003c/code\u003e, which is more specific than both \u003ccode\u003erule1\u003c/code\u003e and \u003ccode\u003erule2\u003c/code\u003e. As a result, the corresponding pipeline will be executed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHowever, even though the request to \u003ccode\u003e/files/team4/document.pdf\u003c/code\u003e matches the path defined in \u003ccode\u003erule2\u003c/code\u003e, the regular expression \u003ccode\u003e(team1|team2)\u003c/code\u003e used in the \u003ccode\u003epath_params\u003c/code\u003e for the \u003ccode\u003eteam\u003c/code\u003e parameter will not match. Since \u003ccode\u003ebacktracking_enabled\u003c/code\u003e is set to \u003ccode\u003etrue\u003c/code\u003e, backtracking will occur, and the request will be matched by \u003ccode\u003erule1\u003c/code\u003e, with its pipeline then being executed.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs described in the \u003ca href=\"/docs/concepts/pipelines/\"\u003eConcepts\u003c/a\u003e section, this pipeline consists of mechanisms, previously configured in the \u003ca href=\"/docs/mechanisms/catalogue/\"\u003emechanisms catalogue\u003c/a\u003e, organized in stages as described below, with authentication stage (consisting of \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eauthenticators\u003c/a\u003e) being mandatory.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eAuthentication Stage:\u003c/strong\u003e List of \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eauthenticator\u003c/a\u003e references using \u003ccode\u003eauthenticator\u003c/code\u003e as key, followed by the required authenticator \u003ccode\u003eid\u003c/code\u003e. Authenticators following the first defined in the list are used by heimdall as fallback. That is, if first authenticator fails due to missing authentication data, second is executed, etc. By default, fallback is not used if an authenticator fails due to validation errors of the given authentication data. E.g. if an authenticator fails to validate the signature of a JWT token, the next authenticator in the list will not be executed. Instead, the entire pipeline will fail and lead to the execution of the \u003ca href=\"#_error_pipeline\"\u003eerror pipeline\u003c/a\u003e. This list is mandatory if no \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e is configured.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nSome authenticators use the same sources to get subject authentication object from. E.g. the \u003ccode\u003ejwt\u003c/code\u003e and the \u003ccode\u003eoauth2_introspection\u003c/code\u003e authenticators can retrieve tokens from the same places in the request. If such authenticators are used in the same pipeline, you should configure the more specific ones before the more general ones to have working default fallbacks. To stay with the above example, the \u003ccode\u003ejwt\u003c/code\u003e authenticator is more specific compared to \u003ccode\u003eoauth2_introspection\u003c/code\u003e, as it will be only executed, if the token is in a JWT format. In contrast to this, the \u003ccode\u003eoauth2_introspection\u003c/code\u003e authenticator is more general and does not care about the token format, thus will feel responsible for the request as soon as it finds a bearer token. You can however also make use of the \u003ccode\u003eallow_fallback_on_error\u003c/code\u003e configuration property and set it to \u003ccode\u003etrue\u003c/code\u003e. This will allow a fallback even if the verification of the credentials fail.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eAuthorization Stage:\u003c/strong\u003e List of \u003ca href=\"/docs/mechanisms/contextualizers/\"\u003econtextualizer\u003c/a\u003e and \u003ca href=\"/docs/mechanisms/authorizers/\"\u003eauthorizer\u003c/a\u003e references in any order (optional). Can also be mixed. As with authenticators, the list definition happens using either \u003ccode\u003econtextualizer\u003c/code\u003e or \u003ccode\u003eauthorizer\u003c/code\u003e as key, followed by the required \u003ccode\u003eid\u003c/code\u003e. All mechanisms in this list are executed in the order, they are defined. If any of these fails, the entire pipeline fails, which leads to the execution of the \u003ca href=\"#_error_pipeline\"\u003eerror pipeline\u003c/a\u003e. This list is optional.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eFinalization Stage:\u003c/strong\u003e List of \u003ca href=\"/docs/mechanisms/finalizers/\"\u003efinalizer\u003c/a\u003e references using \u003ccode\u003efinalizers\u003c/code\u003e as key, followed by the required finalizer \u003ccode\u003eid\u003c/code\u003e. All finalizers in this list are executed in the order they are defined. If any of these fail, the entire pipeline fails, which leads to the execution of the \u003ca href=\"#_error_pipeline\"\u003eerror pipeline\u003c/a\u003e. This list is optional. If a \u003ca href=\"/docs/rules/default_rule/\"\u003edefault rule\u003c/a\u003e is configured, and no \u003ccode\u003efinalizers\u003c/code\u003e are configured on a specific rule level, the \u003ccode\u003efinalizers\u003c/code\u003e from the default rule are used. If the default rule does not have any \u003ccode\u003efinalizers\u003c/code\u003e configured either, no finalization will take place.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn all cases, the used mechanism can be partially reconfigured if supported by the corresponding type. Configuration goes into the \u003ccode\u003econfig\u003c/code\u003e properties. These reconfigurations are always local to the given rule. With other words, you can adjust your rule specific pipeline as you want without any side effects.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExecution of an \u003ccode\u003econtextualizer\u003c/code\u003e, \u003ccode\u003eauthorizer\u003c/code\u003e, or \u003ccode\u003efinalizer\u003c/code\u003e mechanisms can optionally happen conditionally by making use of a \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e expression in an \u003ccode\u003eif\u003c/code\u003e clause, which has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_subject\"\u003e\u003ccode\u003eSubject\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects. If the \u003ccode\u003eif\u003c/code\u003e clause is not present, the corresponding mechanism is always executed.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Complex pipeline\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"c1\"\u003e# list of authenticators\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# defining the authentication stage\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanon\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# ... any further required authenticator\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# list of authorizers and contextualizers in any order\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# defining the authentication stage\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebaz\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e0s\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ezab\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSubject.ID != \u0026#34;anonymous\u0026#34;\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003econtextualizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRequest.Method == \u0026#34;POST\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e// some expression logic deviating from the\u003c/span\u003e\n \u003cspan class=\"s\"\u003e// definition in the pipeline configuration.\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# ... any further required authorizer or contextualizer\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# list of finalizers\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e# defining the finalization stage\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eX-User-ID\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{{\u003c/span\u003e \u003cspan class=\"nv\"\u003equote .ID\u003c/span\u003e \u003cspan class=\"pi\"\u003e}}\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# ... any further required finalizers\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example uses\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003etwo authenticators, with authenticator named \u003ccode\u003ebar\u003c/code\u003e being the fallback for the authenticator named \u003ccode\u003efoo\u003c/code\u003e. This fallback authenticator is obviously of type \u003ca href=\"/docs/mechanisms/authenticators/#_anonymous\"\u003eanonymous\u003c/a\u003e as it reconfigures the referenced prototype to use \u003ccode\u003eanon\u003c/code\u003e for subject id.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003emultiple contextualizers and authorizers, with first contextualizer having its cache disabled (\u003ccode\u003ecache_ttl\u003c/code\u003e set to 0s) and the last authorizer being of type \u003ca href=\"/docs/mechanisms/authorizers/#_local_cel\"\u003ecel\u003c/a\u003e as it reconfigures the referenced prototype to use a different authorization expression.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003etwo finalizers, with the second one being obviously of type \u003ca href=\"/docs/mechanisms/finalizers/#_header\"\u003eheader\u003c/a\u003e, as it defines a \u003ccode\u003eX-User-ID\u003c/code\u003e header set to the value of the subject id to be forwarded to the upstream service.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003econtextualizer \u003ccode\u003efoo\u003c/code\u003e is only executed if the authenticated subject is not anonymous.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eauthorizer \u003ccode\u003efoo\u003c/code\u003e is only executed if the request method is HTTP POST.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_error_pipeline\"\u003eError Pipeline\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCompared to the \u003ca href=\"#_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/a\u003e, the error pipeline is pretty simple. It is also a list of mechanism references, but all referenced types are \u003ca href=\"/docs/mechanisms/error_handlers/\"\u003eerror handler types\u003c/a\u003e. Thus, each entry in this list must have \u003ccode\u003eerror_handler\u003c/code\u003e as key, followed by the \u003ccode\u003eìd\u003c/code\u003e of the required error handler previously defined in the \u003ca href=\"/docs/mechanisms/catalogue/\"\u003emechanism catalogue\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eExecution of the error handlers should happen conditionally by making use of a \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e expression in an \u003ccode\u003eif\u003c/code\u003e clause, which has access to the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_error\"\u003e\u003ccode\u003eError\u003c/code\u003e\u003c/a\u003e and the \u003ca href=\"/docs/mechanisms/evaluation_objects/#_request\"\u003e\u003ccode\u003eRequest\u003c/code\u003e\u003c/a\u003e objects. Otherwise, the first error handler will be executed and the error pipeline will exit.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with the authentication \u0026amp; authorization pipeline, partial reconfiguration of the used mechanisms is possible if supported by the corresponding type. The overrides are always local to the given rule as well.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Two error handlers\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"c1\"\u003e# rule specific condition\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# rule specific config\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example uses two error handlers, named \u003ccode\u003efoo\u003c/code\u003e and \u003ccode\u003ebar\u003c/code\u003e. \u003ccode\u003ebar\u003c/code\u003e will only be executed if \u003ccode\u003efoo\u003c/code\u003e \u0026#39;s error condition does not match. \u003ccode\u003ebar\u003c/code\u003e does also override the error handler configuration as required by the given rule.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Rules"],"tags":null,"title":"Regular Rule","url":"/docs/rules/regular_rule/"},{"categories":null,"content":" Configuration The default rule can be configured using the default_rule property supporting the options shown below.\nThe default rule does not support all properties available in a regular rule.\nIt cannot be used to forward requests to an upstream service protected by heimdall. If heimdall is operating in reverse proxy mode, the default rule should be configured to reject requests. Otherwise, Heimdall will respond with an error.\nThe default rule also rejects requests containing encoded slashes in the URL path with a 400 Bad Request response. In a regular rule, this behavior can be configured.\nThe authentication stage cannot start with an insecure authenticator (i.e., authenticators that allow all requests to pass through). However, this enforcement can be disabled (not recommended) by starting heimdall with the --insecure-skip-secure-default-rule-enforcement flag.\nbacktracking_enabled: boolean (optional)\nEnables or disables backtracking while matching the rules globally. Defaults to false.\nexecute: Authentication \u0026amp; Authorization Pipeline (mandatory)\nWhich mechanisms to use for authentication, authorization and finalization stages of the pipeline. At least the authentication stage with at least one authenticator must be defined. A specific rule (see also Regular Rule) can omit the definition of that stage, if it wants to reuse it from in the default rule. Same is true for other stages (See also Rule Inheritance).\non_error: Error Pipeline (optional)\nWhich error handler mechanisms to use if any of the mechanisms, defined in the execute property fail. Allows omitting the definition of error handlers in specific rules. As soon as a specific rule defines at least one error handler mechanism, all error handler mechanisms, defined in the default rule are ignored. If not specified, the default error handler is used.\nExample 1. Default rule configuration default_rule: execute: - authenticator: session_cookie_from_kratos_authn - authenticator: oauth2_introspect_token_from_keycloak_authn - authorizer: deny_all_requests_authz - finalizer: create_jwt on_error: - error_handler: authenticate_with_kratos_eh if: | type(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;session_cookie_from_kratos_authn\u0026#34; This example defines a default rule, with the authentication 6 authorization pipeline consisting of two authenticators, with session_cookie_from_kratos_authn being the first and oauth2_introspect_token_from_keycloak_authn being the fallback one (if the first one fails), a deny_all_requests_authz authorizer and the create_jwt finalizer. The error pipeline is configured to execute only the authenticate_with_kratos_eh error handler.\nObviously, the authentication \u0026amp; authorization pipeline (defined in the execute property) of this default rule will always result in an error due to deny_all_requests_authz. This way it is thought to provide secure defaults and let the upstream specific (regular) rules override at least the part dealing with authorization. Such an upstream specific rule could then look like follows:\nid: rule:my-service:protected-api match: routes: - path: /foo execute: - authorizer: allow_all_requests_authz Take a look at how on_error, as well as the authenticators and finalizers from the execute definition of the default rule are reused. Easy, no?\n","description":"Heimdall lets you not only define upstream service specific rules, it does also support a definition of an optional default rule, which, if defined, kicks in, if no other rule matches. This way you can ensure secure defaults by simultaneously reducing the amount of work while defining upstream service API specific rules.","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_configuration\"\u003eConfiguration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe default rule can be configured using the \u003ccode\u003edefault_rule\u003c/code\u003e property supporting the options shown below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe default rule does not support all properties available in a \u003ca href=\"/docs/rules/regular_rule/\"\u003eregular rule\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIt cannot be used to forward requests to an upstream service protected by heimdall. If heimdall is operating in reverse proxy mode, the default rule should be configured to reject requests. Otherwise, Heimdall will respond with an error.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe default rule also rejects requests containing encoded slashes in the URL path with a \u003ccode\u003e400 Bad Request\u003c/code\u003e response. In a regular rule, this behavior can be configured.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eThe authentication stage cannot start with an insecure authenticator (i.e., authenticators that allow all requests to pass through). However, this enforcement can be disabled (not recommended) by starting heimdall with the \u003ccode\u003e--insecure-skip-secure-default-rule-enforcement\u003c/code\u003e flag.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebacktracking_enabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables or disables backtracking while matching the rules globally. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexecute\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/rules/regular_rule/#_authentication_authorization_pipeline\"\u003eAuthentication \u0026amp; Authorization Pipeline\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhich mechanisms to use for authentication, authorization and finalization stages of the pipeline. At least the authentication stage with at least one \u003ca href=\"/docs/mechanisms/authenticators/\"\u003eauthenticator\u003c/a\u003e must be defined. A specific rule (see also \u003ca href=\"/docs/rules/regular_rule/\"\u003eRegular Rule\u003c/a\u003e) can omit the definition of that stage, if it wants to reuse it from in the default rule. Same is true for other stages (See also \u003ca href=\"/docs/concepts/rules/#_default_rule_inheritance\"\u003eRule Inheritance\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eon_error\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/rules/regular_rule/#_error_pipeline\"\u003eError Pipeline\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhich error handler mechanisms to use if any of the mechanisms, defined in the \u003ccode\u003eexecute\u003c/code\u003e property fail. Allows omitting the definition of error handlers in specific rules. As soon as a specific rule defines at least one error handler mechanism, all error handler mechanisms, defined in the default rule are ignored. If not specified, the default error handler is used.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Default rule configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003edefault_rule\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esession_cookie_from_kratos_authn\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_introspect_token_from_keycloak_authn\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all_requests_authz\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecreate_jwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003eon_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticate_with_kratos_eh\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;session_cookie_from_kratos_authn\u0026#34;\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example defines a default rule, with the authentication 6 authorization pipeline consisting of two authenticators, with \u003ccode\u003esession_cookie_from_kratos_authn\u003c/code\u003e being the first and \u003ccode\u003eoauth2_introspect_token_from_keycloak_authn\u003c/code\u003e being the fallback one (if the first one fails), a \u003ccode\u003edeny_all_requests_authz\u003c/code\u003e authorizer and the \u003ccode\u003ecreate_jwt\u003c/code\u003e finalizer. The error pipeline is configured to execute only the \u003ccode\u003eauthenticate_with_kratos_eh\u003c/code\u003e error handler.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eObviously, the authentication \u0026amp; authorization pipeline (defined in the \u003ccode\u003eexecute\u003c/code\u003e property) of this default rule will always result in an error due to \u003ccode\u003edeny_all_requests_authz\u003c/code\u003e. This way it is thought to provide secure defaults and let the upstream specific (regular) rules override at least the part dealing with authorization. Such an upstream specific rule could then look like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:my-service:protected-api\u003c/span\u003e\n\u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/foo\u003c/span\u003e\n\u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow_all_requests_authz\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTake a look at how \u003ccode\u003eon_error\u003c/code\u003e, as well as the authenticators and finalizers from the \u003ccode\u003eexecute\u003c/code\u003e definition of the default rule are reused. Easy, no?\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Rules"],"tags":null,"title":"Default Rule","url":"/docs/rules/default_rule/"},{"categories":null,"content":" Depending on the configured provider, the rules can be then loaded from e.g. a plain old configuration file, residing in the local file system, or even from a Kubernetes environment as a custom resource. Thus, the structure and format of a rule set depends on the provider used to load it. As of today, there are two supported formats:\nas a regular JSON/YAML file, the so-called regular rule set, and\nas a kubernetes custom resource rule set, which is actually a YAML/JSON file as well, but adheres to corresponding kubernetes requirements.\nThe main difference is the internal structure. Both do however require the specification of a version and a list or rules.\nRegular Rule Set A regular rule set is a just a file with a list of rules and some additional meta information. Latter can be extended by a particular provider supporting that format.\nAvailable properties are:\nversion: string (mandatory)\nThe version schema of the rule set. The current version of heimdall supports only the version 1alpha4.\nname: string (optional)\nThe name of a rule set. Used only for logging purposes.\nrules: Rule Configuration array (mandatory)\nThe list of the actual rule definitions.\nExample 1. Rule set with two rules An imaginary rule set file defining two rules could look like shown below.\nversion: \u0026#34;1alpha4\u0026#34; name: my-rule-set rules: - id: rule:1 match: routes: - path: /** methods: [ \u0026#34;GET\u0026#34; ] scheme: https hosts: - type: exact value: my-service1.local execute: - authorizer: foobar - id: rule:2 match: routes: - path: /** scheme: https hosts: - type: exact value: my-service2.local methods: [ \u0026#34;GET\u0026#34; ] execute: - authorizer: barfoo Kubernetes Rule Set If you operate heimdall in kubernetes, most probably, you would like to make use of the RuleSet custom resource, which can be loaded by the kubernetes provider.\nConfiguration apiVersion: string (mandatory)\nThe api version of the custom resource definition, the given rule set is based on. The current version of heimdall supports only heimdall.dadrus.github.com/v1alpha4 version.\nkind: string (mandatory)\nThe custom resource kind. Must be set to RuleSet\nmetadata: map (optional)\nThe metadata, you would like to assign to the rule set, like the name of the rule set, labels, etc\nspec: map (mandatory)\nThe actual specification of the rule set. Following properties are possible, respectively required:\nauthClassName: string (optional)\nReferences the heimdall instance, which should use this RuleSet.\nrules: Rule Configuration array (mandatory)\nThe list of the actual rules.\nTo be able to deploy and make heimdall use the RuleSet custom resources, the corresponding CRD must be deployed. Otherwise, heimdall will not be able to monitor corresponding resources and emit error messages to the log.\nIf you have used the Helm Chart to install heimdall, this CRD is already installed. You can however install it also like this:\n$ kubectl apply -f https://raw.githubusercontent.com/dadrus/heimdall/main/charts/heimdall/crds/ruleset.yaml Example 2. Simple Example apiVersion: heimdall.dadrus.github.com/v1alpha4 kind: RuleSet metadata: name: \u0026#34;\u0026lt;some name\u0026gt;\u0026#34; spec: authClassName: \u0026#34;\u0026lt;optional auth_class reference (see above)\u0026gt; \u0026#34; rules: - id: \u0026#34;\u0026lt;identifier of a rule 1\u0026gt;\u0026#34; match: routes: - path: /foo/** scheme: https hosts: - type: exact value: 127.0.0.1:9090 execute: - authenticator: foo - authorizer: bar Resource Status In addition to configuration properties described above, a RuleSet resource has a status stanza, which provides information about the usage status as soon as a RuleSet has been loaded by at least one heimdall instance.\nBy making use of kubectl get -n \u0026lt;your namespace\u0026gt; rulesets.heimdall.dadrus.github.com you’ll get an overview of deployed RuleSet resources in a particular namespace, like e.g. shown below\nNAME ACTIVE IN AGE test-rules 2/2 32m The value 2/2 in ACTIVE IN means, \u0026lt;active in heimdall instances\u0026gt;/\u0026lt;matching instances\u0026gt;. With\n\u0026#34;matching instances\u0026#34; being those heimdall instances, which auth_class matches the authClassName in the RuleSet and\n\u0026#34;active in heimdall instances\u0026#34; are those from the \u0026#34;matching instances\u0026#34;, which were able to load the RuleSet.\nIn addition, you can also get further information about the executed reconciliations by the deployed heimdall instances by taking a look at the .status.conditions field. The reconciliation status of matching instances is present there. That also means, if there were errors while loading the RuleSet, these are present in this condition list\nE.g.\n$ kubectl describe -n test rulesets.heimdall.dadrus.github.com test-rules Name: test-rules Namespace: test ... Status: Conditions: Last Transition Time: 2023-11-08T21:55:36Z Message: heimdall-6fb66c47bc-kwqqn instance successfully loaded RuleSet Observed Generation: 1 Reason: RuleSetActive Status: True Type: heimdall-6fb66c47bc-kwqqn/Reconciliation Last Transition Time: 2023-11-08T21:55:36Z Message: heimdall-6fb66c47bc-l7skn instance successfully loaded RuleSet Observed Generation: 1 Reason: RuleSetActive Status: True Type: heimdall-6fb66c47bc-l7skn/Reconciliation Active In: 2/2 Events: \u0026lt;none\u0026gt; ","description":"Rule Sets organize rules, allowing versioning of such and loading by providers.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDepending on the configured provider, the rules can be then loaded from e.g. a plain old configuration file, residing in the local file system, or even from a Kubernetes environment as a custom resource. Thus, the structure and format of a rule set depends on the \u003ca href=\"/docs/rules/providers/\"\u003eprovider\u003c/a\u003e used to load it. As of today, there are two supported formats:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eas a regular JSON/YAML file, the so-called \u003ca href=\"#_regular_rule_set\"\u003eregular rule set\u003c/a\u003e, and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eas a kubernetes \u003ca href=\"#_kubernetes_rule_set\"\u003ecustom resource rule set\u003c/a\u003e, which is actually a YAML/JSON file as well, but adheres to corresponding kubernetes requirements.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe main difference is the internal structure. Both do however require the specification of a version and a list or rules.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_regular_rule_set\"\u003eRegular Rule Set\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA regular rule set is a just a file with a list of rules and some additional meta information. Latter can be extended by a particular \u003ca href=\"/docs/rules/providers/\"\u003eprovider\u003c/a\u003e supporting that format.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAvailable properties are:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eversion\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe version schema of the rule set. The current version of heimdall supports only the version \u003ccode\u003e1alpha4\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of a rule set. Used only for logging purposes.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003erules\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/rules/regular_rule/#_configuration\"\u003eRule Configuration\u003c/a\u003e array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe list of the actual rule definitions.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Rule set with two rules\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAn imaginary rule set file defining two rules could look like shown below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-rule-set\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/**\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eGET\u0026#34;\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-service1.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:2\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/**\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-service2.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eGET\u0026#34;\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebarfoo\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_kubernetes_rule_set\"\u003eKubernetes Rule Set\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you operate heimdall in kubernetes, most probably, you would like to make use of the \u003ccode\u003eRuleSet\u003c/code\u003e custom resource, which can be loaded by the \u003ca href=\"/docs/rules/providers/#_kubernetes\"\u003ekubernetes provider\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eapiVersion\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe api version of the custom resource definition, the given rule set is based on. The current version of heimdall supports only \u003ccode\u003eheimdall.dadrus.github.com/v1alpha4\u003c/code\u003e version.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ekind\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe custom resource kind. Must be set to \u003ccode\u003eRuleSet\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emetadata\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emap\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe metadata, you would like to assign to the rule set, like the name of the rule set, labels, etc\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003espec\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003emap\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual specification of the rule set. Following properties are possible, respectively required:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauthClassName\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eReferences the heimdall instance, which should use this \u003ccode\u003eRuleSet\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003erules\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/rules/regular_rule/#_configuration\"\u003eRule Configuration\u003c/a\u003e array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe list of the actual rules.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo be able to deploy and make heimdall use the \u003ccode\u003eRuleSet\u003c/code\u003e custom resources, the corresponding CRD must be deployed. Otherwise, heimdall will not be able to monitor corresponding resources and emit error messages to the log.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you have used the \u003ca href=\"/docs/getting_started/installation/#_helm_chart\"\u003eHelm Chart\u003c/a\u003e to install heimdall, this CRD is already installed. You can however install it also like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ekubectl apply \u003cspan class=\"nt\"\u003e-f\u003c/span\u003e https://raw.githubusercontent.com/dadrus/heimdall/main/charts/heimdall/crds/ruleset.yaml\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Simple Example\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eapiVersion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheimdall.dadrus.github.com/v1alpha4\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekind\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eRuleSet\u003c/span\u003e\n\u003cspan class=\"na\"\u003emetadata\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026lt;some\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ename\u0026gt;\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003espec\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthClassName\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026lt;optional\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eauth_class\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ereference\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e(see\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eabove)\u0026gt;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026lt;identifier\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eof\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ea\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003erule\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e1\u0026gt;\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/foo/**\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1:9090\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_resource_status\"\u003eResource Status\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition to configuration properties described above, a \u003ccode\u003eRuleSet\u003c/code\u003e resource has a \u003ccode\u003estatus\u003c/code\u003e stanza, which provides information about the usage status as soon as a \u003ccode\u003eRuleSet\u003c/code\u003e has been loaded by at least one heimdall instance.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of \u003ccode\u003ekubectl get -n \u0026lt;your namespace\u0026gt; rulesets.heimdall.dadrus.github.com\u003c/code\u003e you’ll get an overview of deployed \u003ccode\u003eRuleSet\u003c/code\u003e resources in a particular namespace, like e.g. shown below\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003eNAME ACTIVE IN AGE\ntest-rules 2/2 32m\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe value \u003ccode\u003e2/2\u003c/code\u003e in \u003ccode\u003eACTIVE IN\u003c/code\u003e means, \u0026lt;active in heimdall instances\u0026gt;/\u0026lt;matching instances\u0026gt;. With\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u0026#34;matching instances\u0026#34; being those heimdall instances, which \u003ccode\u003eauth_class\u003c/code\u003e matches the \u003ccode\u003eauthClassName\u003c/code\u003e in the \u003ccode\u003eRuleSet\u003c/code\u003e and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u0026#34;active in heimdall instances\u0026#34; are those from the \u0026#34;matching instances\u0026#34;, which were able to load the \u003ccode\u003eRuleSet\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn addition, you can also get further information about the executed reconciliations by the deployed heimdall instances by taking a look at the \u003ccode\u003e.status.conditions\u003c/code\u003e field. The reconciliation status of matching instances is present there. That also means, if there were errors while loading the \u003ccode\u003eRuleSet\u003c/code\u003e, these are present in this condition list\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eE.g.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ekubectl describe \u003cspan class=\"nt\"\u003e-n\u003c/span\u003e \u003cspan class=\"nb\"\u003etest \u003c/span\u003erulesets.heimdall.dadrus.github.com test-rules\n\nName: test-rules\nNamespace: \u003cspan class=\"nb\"\u003etest\u003c/span\u003e\n...\nStatus:\n Conditions:\n Last Transition Time: 2023-11-08T21:55:36Z\n Message: heimdall-6fb66c47bc-kwqqn instance successfully loaded RuleSet\n Observed Generation: 1\n Reason: RuleSetActive\n Status: True\n Type: heimdall-6fb66c47bc-kwqqn/Reconciliation\n Last Transition Time: 2023-11-08T21:55:36Z\n Message: heimdall-6fb66c47bc-l7skn instance successfully loaded RuleSet\n Observed Generation: 1\n Reason: RuleSetActive\n Status: True\n Type: heimdall-6fb66c47bc-l7skn/Reconciliation\n Active In: 2/2\n Events: \u0026lt;none\u0026gt;\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Rules"],"tags":null,"title":"Rule Sets","url":"/docs/rules/rule_sets/"},{"categories":null,"content":" Providers allow definition of sources to load the rule sets from. These make heimdall’s behavior dynamic. All providers, you want to enable for a heimdall instance must be configured within the providers section of heimdall’s configuration.\nBelow, you can find the description and configuration options for currently supported providers.\nFilesystem The filesystem provider allows loading of regular rule sets in JSON or YAML format from a file system.\nConfiguration The configuration of this provider goes into the file_system property. This provider is handy for e.g. starting playing around with heimdall, e.g. locally, or using a container runtime, as well as if your deployment strategy considers deploying a heimdall instance as a Side-Car for each of your services.\nFollowing configuration options are supported:\nsrc: string (mandatory)\nCan either be a single file, containing a rule set, or a directory with files, each containing a rule set.\nwatch: boolean (optional)\nWhether the configured src should be watched for updates. Defaults to false. If the src has been configured to a single file, the provider will watch for changes in that file. Otherwise, if the src has been configured to a directory, the provider will watch for files appearing and disappearing in this directory, as well as for changes in each particular file in this directory. Recursive lookup is not supported. That is, if the configured directory contains further directories, these, as well as their contents are ignored.\nenv_vars_enabled: boolean (optional)\nWhether to enable environment variables access in the rule set files. Defaults to false. If set to true, environment variables usage using Bash syntax is possible as with the static configuration.\nAll environment variables, used in the rule set files must be known in advance to the heimdall process (when it starts). In addition, the usage of that functionality might lead to security issues. If an adversary is somehow able to add new or update existing rule sets, it would be theoretically able exfiltrating environment variables available to the heimdall process by crafting contextualizers or authorizers, which would forward the corresponding values to a controlled service. So, use with caution, disable the watching of rule set updates and try to avoid! Example 1. Rule set making use of environment variables version: \u0026#34;1alpha4\u0026#34; name: my-rule-set rules: - id: rule:1 match: routes: - path: /** hosts: - type: exact value: my-service1.local methods: [ \u0026#34;GET\u0026#34; ] forward_to: host: ${UPSTREAM_HOST:=\u0026#34;default-backend:8080\u0026#34;} execute: - authorizer: foobar Examples Example 2. Load rule sets from the files residing in the /path/to/rules/dir directory and watch for changes. file_system: src: /path/to/rules/dir watch: true Example 3. Load rule sets from the /path/to/rules.yaml file without watching it for changes. file_system: src: /path/to/rules.yaml HTTP Endpoint This provider allows loading of regular rule sets in JSON or YAML format from any remote endpoint accessible via HTTP(s). The format selection happens based on the Content-Type set in the response from the endpoint, which must be either application/yaml or application/json, otherwise an error is logged and the response from the endpoint is ignored.\nThe loading and removal of rules happens as follows:\nif the response status code is an HTTP 200 OK and contains a rule sets in a known format (see above), the corresponding rules are loaded (if the definitions are valid)\nin case of network issues, like dns errors, timeouts and alike, the rule sets previously received from the corresponding endpoints are preserved.\nin any other case related to network communication (e.g. not 200 status code, empty response body, unsupported format, etc.), the corresponding rules are removed if previously loaded.\nConfiguration The configuration of this provider goes into the http_endpoint property. In contrast to the Filesystem provider, it can be configured with as many endpoints to load rule sets from as required for the particular use case.\nFollowing configuration options are supported:\nwatch_interval: Duration (optional)\nWhether the configured endpoints should be polled for updates. Defaults to 0s (polling disabled).\nendpoints: Endpoint array (mandatory)\nEach entry of that array supports all the properties defined by Endpoint, except method, which is always GET. As with the Endpoint type, at least the url must be configured.\nHTTP caching according to RFC 7234 is enabled by default. It can be disabled on the particular endpoint by setting http_cache.enabled to false. Examples Example 4. Minimal possible configuration Here the provider is configured to load a rule set from one endpoint without polling it for changes.\nhttp_endpoint: endpoints: - url: https://foo.bar/ruleset1 Example 5. Load rule sets from remote endpoints and watch for changes. Here, the provider is configured to poll the two defined rule set endpoints for changes every 5 minutes.\nThe configuration for both endpoints instructs heimdall to disable HTTP caching. The configuration of the second endpoint uses a couple of additional properties. One to ensure the communication to that endpoint is more resilient by setting the retry options and since this endpoint is protected by an API key, it defines the corresponding options as well.\nhttp_endpoint: watch_interval: 5m endpoints: - url: https://foo.bar/ruleset1 http_cache: enabled: false - url: https://foo.bar/ruleset2 http_cache: enabled: false retry: give_up_after: 5s max_delay: 250ms auth: type: api_key config: name: X-Api-Key value: super-secret in: header Cloud Blob This provider allows loading of regular rule sets from cloud blobs, like AWS S3 buckets, Google Cloud Storage, Azure Blobs, or other API compatible implementations and supports rule sets in YAML, as well as in JSON format. The format selection happens based on the Content-Type set in the metadata of the loaded blob, which must be either application/yaml or application/json, otherwise an error is logged and the blob is ignored.\nThe loading and removal of rules happens as follows:\nif the response status code is an HTTP 200 OK and contains a rule set in a known format (see above), the corresponding rules are loaded (if the definitions are valid)\nin case of network issues, like dns errors, timeouts and alike, the rule sets previously received from the corresponding buckets are preserved.\nin any other case like, not 200 status code, empty response body, unsupported format, etc, the corresponding rules are removed if previously loaded.\nConfiguration The configuration of this provider goes into the cloud_blob property. As with HTTP Endpoint provider, it can be configured with as many buckets/blobs to load rule sets from as required for the particular use case.\nFollowing configuration options are supported:\nwatch_interval: Duration (optional)\nWhether the configured buckets should be polled for updates. Defaults to 0s (polling disabled).\nbuckets: BlobReference array (mandatory)\nEach BlobReference entry in that array supports the following properties:\nurl: string (mandatory)\nThe actual url to the bucket or to a specific blob in the bucket.\nprefix: string (optional)\nIndicates that only blobs with a key starting with this prefix should be retrieved\nThe differentiation which storage is used is based on the URL scheme. These are:\ns3 for AWS S3 buckets\ngs for Google Cloud Storage and\nazblob for Azure Blob Storage\nOther API compatible storage services, like Minio, Ceph, SeaweedFS, etc. can be used as well. The corresponding and other options can be found in the Go CDK Blob documentation, the implementation of this provider is based on.\nThe communication to the storage services requires an active session to the corresponding cloud provider. The session information is taken from the vendor specific environment variables, respectively configuration. See AWS Session, GC Application Default Credentials and Azure Storage Access for more information. Examples Example 6. Minimal possible configuration Here the provider is configured to load rule sets from all blobs stored on the Google Cloud Storage bucket named \u0026#34;my-bucket\u0026#34; without polling for changes.\ncloud_blob: buckets: - url: gs://my-bucket Example 7. Load rule sets from AWS S3 buckets and watch for changes. cloud_blob: watch_interval: 2m buckets: - url: gs://my-bucket prefix: service1 - url: gs://my-bucket prefix: service2 - url: s3://my-bucket/my-rule-set?region=us-west-1 Here, the provider is configured to poll multiple buckets with rule sets for changes every 2 minutes.\nThe first two bucket reference configurations reference actually the same bucket on Google Cloud Storage, but different blobs based on the configured blob prefix. The first one will let heimdall loading only those blobs, which start with service1, the second only those, which start with service2.\nThe last one instructs heimdall to load rule set from a specific blob, namely a blob named my-rule-set, which resides on the my-bucket AWS S3 bucket, which is located in the us-west-1 AWS region.\nKubernetes This provider is only supported if heimdall is running within Kubernetes and allows usage (validation and loading) of RuleSet custom resources deployed to the same Kubernetes environment.\nConfiguration The configuration of this provider goes into the kubernetes property and supports the following configuration options:\nauth_class: string (optional)\nBy making use of this property, you can specify which rule sets should be used by this particular heimdall instance. If specified, heimdall will consider the value of the authClassName attribute of each RuleSet resource deployed to the cluster and validate, respectively load only those rules, which authClassName values matching the value of auth_class. If not set all RuleSet resources will be used.\ntls: TLS (optional)\nIf configured, heimdall will start and expose a validating admission controller service on port 4458 listening on all interfaces. This service allows integration with the Kubernetes API server enabling validation of the applied RuleSet resources before these are made available to heimdall for loading. This way you will get a direct feedback about issues without the need to look into heimdall logs if a RuleSet resource could not be loaded (See also API documentation for more details).\nTo let the Kubernetes API server use the admission controller, there is a need for a properly configured ValidatingWebhookConfiguration. The Helm Chart shipped with heimdall does this automatically as soon as this property is configured. It does however need a caBundle to be set or injected. Otherwise, the Kubernetes API server won’t trust the configured TLS certificate and won’t use the endpoint.\nSince multiple heimdall deployments with different configured auth_class names can coexist, RuleSet resources with mismatching authClassName will be ignored by a particular deployment. In addition, Kubernetes API server validation requests for mismatching rule sets result in a successful response. This behavior is required as otherwise, as soon as the API server receives even a single failed validation response, the affected RuleSet resource will be discarded and not made available for loading to any of the available heimdall deployments.\nThat also means, if there is no heimdall deployment feeling responsible for the given RuleSet resource (due to authClassName - auth_class mismatch), the affected RuleSet resource will be silently ignored.\nExamples Example 8. Minimal possible configuration Here, the provider is just enabled. Since no auth_class is configured, it will load all RuleSet resources deployed to the Kubernetes environment.\nkubernetes: {} Example 9. Configuration with auth_class set Here, the provider is configured to consider only those RuleSet resources, which authClassName is set to foo.\nkubernetes: auth_class: foo Example 10. Configuration with auth_class set and enabled validating admission controller As with the previous example, the provider is configured to consider only those RuleSet resources, which authClassName is set to foo. The admission controller is enabled as well and will validate RuleSet resources before these are made available for loading.\nkubernetes: auth_class: foo tls: # below is the minimal required configuration key_store: path: /path/to/file.pem This provider requires a RuleSet CRD being deployed, otherwise heimdall will not be able to monitor corresponding resources and emit error messages to the log.\nIf you have used the Helm Chart to install heimdall, this CRD is already installed. You can however install it also like this:\n$ kubectl apply -f https://raw.githubusercontent.com/dadrus/heimdall/main/charts/heimdall/crds/ruleset.yaml ","description":"Rule providers manage rules in heimdall. They load, reload or remove rules when new rule sets appear, changes are detected, or rule sets are deleted.","html_content":"\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eProviders allow definition of sources to load the \u003ca href=\"/docs/rules/rule_sets/\"\u003erule sets\u003c/a\u003e from. These make heimdall’s behavior dynamic. All providers, you want to enable for a heimdall instance must be configured within the \u003ccode\u003eproviders\u003c/code\u003e section of heimdall’s configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBelow, you can find the description and configuration options for currently supported providers.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_filesystem\"\u003eFilesystem\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe filesystem provider allows loading of \u003ca href=\"/docs/rules/rule_sets/#_regular_rule_set\"\u003eregular rule sets\u003c/a\u003e in JSON or YAML format from a file system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this provider goes into the \u003ccode\u003efile_system\u003c/code\u003e property. This provider is handy for e.g. starting playing around with heimdall, e.g. locally, or using a container runtime, as well as if your deployment strategy considers deploying a heimdall instance as a Side-Car for each of your services.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing configuration options are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esrc\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCan either be a single file, containing a rule set, or a directory with files, each containing a rule set.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewatch\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhether the configured \u003ccode\u003esrc\u003c/code\u003e should be watched for updates. Defaults to \u003ccode\u003efalse\u003c/code\u003e. If the \u003ccode\u003esrc\u003c/code\u003e has been configured to a single file, the provider will watch for changes in that file. Otherwise, if the \u003ccode\u003esrc\u003c/code\u003e has been configured to a directory, the provider will watch for files appearing and disappearing in this directory, as well as for changes in each particular file in this directory. Recursive lookup is not supported. That is, if the configured directory contains further directories, these, as well as their contents are ignored.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eenv_vars_enabled\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhether to enable environment variables access in the rule set files. Defaults to \u003ccode\u003efalse\u003c/code\u003e. If set to \u003ccode\u003etrue\u003c/code\u003e, environment variables usage using Bash syntax is possible as with the \u003ca href=\"/docs/operations/configuration/#_configuration_file\"\u003estatic configuration\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nAll environment variables, used in the rule set files must be known in advance to the heimdall process (when it starts). In addition, the usage of that functionality might lead to security issues. If an adversary is somehow able to add new or update existing rule sets, it would be theoretically able exfiltrating environment variables available to the heimdall process by crafting contextualizers or authorizers, which would forward the corresponding values to a controlled service. So, use with caution, disable the watching of rule set updates and try to avoid!\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Rule set making use of environment variables\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eversion\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e1alpha4\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-rule-set\u003c/span\u003e\n\u003cspan class=\"na\"\u003erules\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erule:1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ematch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eroutes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/**\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehosts\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy-service1.local\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eGET\u0026#34;\u003c/span\u003e \u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_to\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e${UPSTREAM_HOST:=\u0026#34;default-backend:8080\u0026#34;}\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthorizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_examples\"\u003eExamples\u003c/h3\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Load rule sets from the files residing in the \u003ccode\u003e/path/to/rules/dir\u003c/code\u003e directory and watch for changes.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/rules/dir\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Load rule sets from the \u003ccode\u003e/path/to/rules.yaml\u003c/code\u003e file without watching it for changes.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/rules.yaml\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_http_endpoint\"\u003eHTTP Endpoint\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis provider allows loading of \u003ca href=\"/docs/rules/rule_sets/#_regular_rule_set\"\u003eregular rule sets\u003c/a\u003e in JSON or YAML format from any remote endpoint accessible via HTTP(s). The format selection happens based on the \u003ccode\u003eContent-Type\u003c/code\u003e set in the response from the endpoint, which must be either \u003ccode\u003eapplication/yaml\u003c/code\u003e or \u003ccode\u003eapplication/json\u003c/code\u003e, otherwise an error is logged and the response from the endpoint is ignored.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe loading and removal of rules happens as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eif the response status code is an HTTP 200 OK and contains a rule sets in a known format (see above), the corresponding rules are loaded (if the definitions are valid)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ein case of network issues, like dns errors, timeouts and alike, the rule sets previously received from the corresponding endpoints are preserved.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ein any other case related to network communication (e.g. not 200 status code, empty response body, unsupported format, etc.), the corresponding rules are removed if previously loaded.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_2\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this provider goes into the \u003ccode\u003ehttp_endpoint\u003c/code\u003e property. In contrast to the \u003ca href=\"#_filesystem\"\u003eFilesystem\u003c/a\u003e provider, it can be configured with as many endpoints to load rule sets from as required for the particular use case.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing configuration options are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewatch_interval\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhether the configured \u003ccode\u003eendpoints\u003c/code\u003e should be polled for updates. Defaults to \u003ccode\u003e0s\u003c/code\u003e (polling disabled).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eendpoints\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach entry of that array supports all the properties defined by \u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e, except \u003ccode\u003emethod\u003c/code\u003e, which is always \u003ccode\u003eGET\u003c/code\u003e. As with the \u003ca href=\"/docs/configuration/types/#_endpoint\"\u003eEndpoint\u003c/a\u003e type, at least the \u003ccode\u003eurl\u003c/code\u003e must be configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nHTTP caching according to \u003ca href=\"https://www.rfc-editor.org/rfc/rfc7234\"\u003eRFC 7234\u003c/a\u003e is enabled by default. It can be disabled on the particular endpoint by setting \u003ccode\u003ehttp_cache.enabled\u003c/code\u003e to \u003ccode\u003efalse\u003c/code\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_examples_2\"\u003eExamples\u003c/h3\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Minimal possible configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere the provider is configured to load a rule set from one endpoint without polling it for changes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ehttp_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar/ruleset1\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Load rule sets from remote endpoints and watch for changes.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, the provider is configured to poll the two defined rule set endpoints for changes every 5 minutes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration for both endpoints instructs heimdall to disable HTTP caching. The configuration of the second endpoint uses a couple of additional properties. One to ensure the communication to that endpoint is more resilient by setting the \u003ccode\u003eretry\u003c/code\u003e options and since this endpoint is protected by an API key, it defines the corresponding options as well.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ehttp_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch_interval\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar/ruleset1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar/ruleset2\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"na\"\u003eretry\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e250ms\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Api-Key\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esuper-secret\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cloud_blob\"\u003eCloud Blob\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis provider allows loading of \u003ca href=\"/docs/rules/rule_sets/#_regular_rule_set\"\u003eregular rule sets\u003c/a\u003e from cloud blobs, like AWS S3 buckets, Google Cloud Storage, Azure Blobs, or other API compatible implementations and supports rule sets in YAML, as well as in JSON format. The format selection happens based on the \u003ccode\u003eContent-Type\u003c/code\u003e set in the metadata of the loaded blob, which must be either \u003ccode\u003eapplication/yaml\u003c/code\u003e or \u003ccode\u003eapplication/json\u003c/code\u003e, otherwise an error is logged and the blob is ignored.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe loading and removal of rules happens as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eif the response status code is an HTTP 200 OK and contains a rule set in a known format (see above), the corresponding rules are loaded (if the definitions are valid)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ein case of network issues, like dns errors, timeouts and alike, the rule sets previously received from the corresponding buckets are preserved.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ein any other case like, not 200 status code, empty response body, unsupported format, etc, the corresponding rules are removed if previously loaded.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_3\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this provider goes into the \u003ccode\u003ecloud_blob\u003c/code\u003e property. As with \u003ca href=\"#_http_endpoint\"\u003eHTTP Endpoint\u003c/a\u003e provider, it can be configured with as many buckets/blobs to load rule sets from as required for the particular use case.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing configuration options are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewatch_interval\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhether the configured \u003ccode\u003ebuckets\u003c/code\u003e should be polled for updates. Defaults to \u003ccode\u003e0s\u003c/code\u003e (polling disabled).\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebuckets\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eBlobReference array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEach \u003cem\u003eBlobReference\u003c/em\u003e entry in that array supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eurl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe actual url to the bucket or to a specific blob in the bucket.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eprefix\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIndicates that only blobs with a key starting with this prefix should be retrieved\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe differentiation which storage is used is based on the URL scheme. These are:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003es3\u003c/code\u003e for \u003ca href=\"https://aws.amazon.com/s3/\"\u003eAWS S3\u003c/a\u003e buckets\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003egs\u003c/code\u003e for \u003ca href=\"https://cloud.google.com/storage/\"\u003eGoogle Cloud Storage\u003c/a\u003e and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eazblob\u003c/code\u003e for \u003ca href=\"https://azure.microsoft.com/en-us/services/storage/blobs/\"\u003eAzure Blob Storage\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eOther API compatible storage services, like \u003ca href=\"https://www.minio.io/\"\u003eMinio\u003c/a\u003e, \u003ca href=\"https://ceph.com/\"\u003eCeph\u003c/a\u003e, \u003ca href=\"https://github.com/chrislusf/seaweedfs\"\u003eSeaweedFS\u003c/a\u003e, etc. can be used as well. The corresponding and other options can be found in the \u003ca href=\"https://gocloud.dev/howto/blob/\"\u003eGo CDK Blob\u003c/a\u003e documentation, the implementation of this provider is based on.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThe communication to the storage services requires an active session to the corresponding cloud provider. The session information is taken from the vendor specific environment variables, respectively configuration. See \u003ca href=\"https://docs.aws.amazon.com/sdk-for-go/api/aws/session/\"\u003eAWS Session\u003c/a\u003e, \u003ca href=\"https://cloud.google.com/docs/authentication/application-default-credentials\"\u003eGC Application Default Credentials\u003c/a\u003e and \u003ca href=\"https://learn.microsoft.com/en-us/azure/storage/common/authorize-data-access?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json\"\u003eAzure Storage Access\u003c/a\u003e for more information.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_examples_3\"\u003eExamples\u003c/h3\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 6. Minimal possible configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere the provider is configured to load rule sets from all blobs stored on the Google Cloud Storage bucket named \u0026#34;my-bucket\u0026#34; without polling for changes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecloud_blob\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuckets\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egs://my-bucket\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 7. Load rule sets from AWS S3 buckets and watch for changes.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ecloud_blob\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch_interval\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2m\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuckets\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egs://my-bucket\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservice1\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egs://my-bucket\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservice2\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003es3://my-bucket/my-rule-set?region=us-west-1\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, the provider is configured to poll multiple buckets with rule sets for changes every 2 minutes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe first two bucket reference configurations reference actually the same bucket on Google Cloud Storage, but different blobs based on the configured blob prefix. The first one will let heimdall loading only those blobs, which start with \u003ccode\u003eservice1\u003c/code\u003e, the second only those, which start with \u003ccode\u003eservice2\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe last one instructs heimdall to load rule set from a specific blob, namely a blob named \u003ccode\u003emy-rule-set\u003c/code\u003e, which resides on the \u003ccode\u003emy-bucket\u003c/code\u003e AWS S3 bucket, which is located in the \u003ccode\u003eus-west-1\u003c/code\u003e AWS region.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_kubernetes\"\u003eKubernetes\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis provider is only supported if heimdall is running within Kubernetes and allows usage (validation and loading) of \u003ca href=\"/docs/rules/rule_sets/#_kubernetes_rule_set\"\u003e\u003ccode\u003eRuleSet\u003c/code\u003e custom resources\u003c/a\u003e deployed to the same Kubernetes environment.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_configuration_4\"\u003eConfiguration\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of this provider goes into the \u003ccode\u003ekubernetes\u003c/code\u003e property and supports the following configuration options:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauth_class\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property, you can specify which rule sets should be used by this particular heimdall instance. If specified, heimdall will consider the value of the \u003ccode\u003eauthClassName\u003c/code\u003e attribute of each \u003ccode\u003eRuleSet\u003c/code\u003e resource deployed to the cluster and validate, respectively load only those rules, which \u003ccode\u003eauthClassName\u003c/code\u003e values matching the value of \u003ccode\u003eauth_class\u003c/code\u003e. If not set all \u003ccode\u003eRuleSet\u003c/code\u003e resources will be used.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etls\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_tls\"\u003eTLS\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf configured, heimdall will start and expose a validating admission controller service on port \u003ccode\u003e4458\u003c/code\u003e listening on all interfaces. This service allows integration with the Kubernetes API server enabling validation of the applied \u003ccode\u003eRuleSet\u003c/code\u003e resources before these are made available to heimdall for loading. This way you will get a direct feedback about issues without the need to look into heimdall logs if a \u003ccode\u003eRuleSet\u003c/code\u003e resource could not be loaded (See also \u003ca href=\"/openapi/#tag/Validating-Admission-Controller\"\u003eAPI\u003c/a\u003e documentation for more details).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo let the Kubernetes API server use the admission controller, there is a need for a properly configured \u003ca href=\"https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#deploy-the-admission-webhook-service\"\u003e\u003ccode\u003eValidatingWebhookConfiguration\u003c/code\u003e\u003c/a\u003e. The \u003ca href=\"https://github.com/dadrus/heimdall/tree/main/charts/heimdall\"\u003eHelm Chart\u003c/a\u003e shipped with heimdall does this automatically as soon as this property is configured. It does however need a \u003ccode\u003ecaBundle\u003c/code\u003e to be set or injected. Otherwise, the Kubernetes API server won’t trust the configured TLS certificate and won’t use the endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince multiple heimdall deployments with different configured \u003ccode\u003eauth_class\u003c/code\u003e names can coexist, \u003ccode\u003eRuleSet\u003c/code\u003e resources with mismatching \u003ccode\u003eauthClassName\u003c/code\u003e will be ignored by a particular deployment. In addition, Kubernetes API server validation requests for mismatching rule sets result in a successful response. This behavior is required as otherwise, as soon as the API server receives even a single failed validation response, the affected \u003ccode\u003eRuleSet\u003c/code\u003e resource will be discarded and not made available for loading to any of the available heimdall deployments.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThat also means, if there is no heimdall deployment feeling responsible for the given \u003ccode\u003eRuleSet\u003c/code\u003e resource (due to \u003ccode\u003eauthClassName\u003c/code\u003e - \u003ccode\u003eauth_class\u003c/code\u003e mismatch), the affected \u003ccode\u003eRuleSet\u003c/code\u003e resource will be silently ignored.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_examples_4\"\u003eExamples\u003c/h3\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 8. Minimal possible configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, the provider is just enabled. Since no \u003ccode\u003eauth_class\u003c/code\u003e is configured, it will load all \u003ccode\u003eRuleSet\u003c/code\u003e resources deployed to the Kubernetes environment.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ekubernetes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e{}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 9. Configuration with \u003ccode\u003eauth_class\u003c/code\u003e set\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere, the provider is configured to consider only those \u003ccode\u003eRuleSet\u003c/code\u003e resources, which \u003ccode\u003eauthClassName\u003c/code\u003e is set to \u003ccode\u003efoo\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ekubernetes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_class\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 10. Configuration with \u003ccode\u003eauth_class\u003c/code\u003e set and enabled validating admission controller\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs with the previous example, the provider is configured to consider only those \u003ccode\u003eRuleSet\u003c/code\u003e resources, which \u003ccode\u003eauthClassName\u003c/code\u003e is set to \u003ccode\u003efoo\u003c/code\u003e. The admission controller is enabled as well and will validate \u003ccode\u003eRuleSet\u003c/code\u003e resources before these are made available for loading.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ekubernetes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_class\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"c1\"\u003e# below is the minimal required configuration\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/file.pem\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis provider requires a RuleSet CRD being deployed, otherwise heimdall will not be able to monitor corresponding resources and emit error messages to the log.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf you have used the \u003ca href=\"/docs/getting_started/installation/#_helm_chart\"\u003eHelm Chart\u003c/a\u003e to install heimdall, this CRD is already installed. You can however install it also like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"bash\"\u003e\u003cspan class=\"nv\"\u003e$ \u003c/span\u003ekubectl apply \u003cspan class=\"nt\"\u003e-f\u003c/span\u003e https://raw.githubusercontent.com/dadrus/heimdall/main/charts/heimdall/crds/ruleset.yaml\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Rules"],"tags":null,"title":"Rule Providers","url":"/docs/rules/providers/"},{"categories":null,"content":" Assertions This type enables configuration of required token and claim assertions. Depending on the object type (JWT or introspection response), the assertions apply to different parts of such objects.\nscopes: Scopes Matcher (optional)\nRequired scopes given to the client.\naudience: string array (optional)\nValues to be matched in the aud claim. This assertion evaluates to true if at least one entry in the given audience array is present in the aud claim. Both cases, either as whitespace separated string, or a JSON array are considered.\nissuers: string array (optional)\nIssuers to trust.\nallowed_algorithms: string array (optional)\nAlgorithms, which are trusted (according to RFC 7518). Defaults to the following list: ES256, ES384, ES512, PS256, PS384, PS512.\nvalidity_leeway Duration (optional)\nThe time leeway to consider while verifying the iat, exp and the nbf. Defaults to 10 seconds.\nExample 1. Assertions configuration issuers: - foo - bar audience: - zap scopes: - baz allowed_algorithms: - ES512 validity_leeway: 5s Here we say, the token must have been issued either by the issuer foo, or the issuer bar, the aud claim must contain zap, the scope claim (either scp or scope) must be present and contain the scope baz, if the token or the introspection response is signed, it must have been signed by using the ES512 algorithm (ECDSA using P-521 and SHA-512) and if the information about token validity is present, we respect a deviation of 5 seconds.\nAuthentication Data Source An authentication data source is actually a list of possible strategies for subject authentication data retrieval. The entries following the first one are fallbacks and are only executed if the previous strategy could not retrieve the required authentication data from the request.\nThis fallback mechanism can become handy, if different clients of your application send the authentication data using different methods. RFC 6750 describes for example how to use bearer tokens in HTTP requests to access OAuth 2.0 protected resources. This RFC says, a token can either be sent in the Authorization header, or in a query parameter, or even as part of the HTTP body. So you can define the following list to let Heimdall try to extract the access token from all three places:\n- header: Authorization scheme: Bearer - query_parameter: access_token - body_parameter: access_token The available strategies are described in the following sections.\nCookie Strategy This strategy can retrieve authentication data from a specific HTTP cookie. Following properties are supported:\ncookie: string (mandatory)\nThe name of the cookie to use.\nExample 2. Cookie Strategy usage Imagine you want Heimdall to verify an authentication session, which is represented by a specific cookie before the request hits your upstream service. If the client of your upstream application, which is case of a cookie would usually be a browser sends a cookie named \u0026#34;session\u0026#34;, you can inform Heimdall to extract and use it by configuring this strategy as follows:\n- cookie: my_session_cookie Header Strategy This strategy can retrieve authentication data from a specific HTTP header. Following properties are supported:\nheader: string (mandatory)\nThe name of the header to use.\nscheme: string (optional)\nScheme, which should be present in the header value. If specified, but not present in the header value, the authentication data cannot be retrieved, effectively making the affected authenticator feel not responsible for the request.\nExample 3. Header Strategy usage Imagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the HTTP Authorization header, you can inform Heimdall to extract it from there by configuring this strategy as follows:\n- header: Authorization scheme: Bearer Query Parameter Strategy query_parameter: string (mandatory)\nThe name of the query parameter to use.\nExample 4. Query Parameter Strategy usage Imagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the query parameter named \u0026#34;access_token\u0026#34;, you can inform Heimdall to extract it from there by configuring this strategy as follows:\n- query_parameter: access_token Body Parameter Strategy The usage of this strategy is only possible when the request payload is either JSON or application/x-www-form-urlencoded encoded. The Content-Type of the request must also either be set to application/x-www-form-urlencoded or to a MIME type, which contains json.\nbody_parameter: string (mandatory)\nThe name of the body parameter to use.\nExample 5. Body Parameter Strategy usage Imagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the body parameter named \u0026#34;access_token\u0026#34;, you can inform Heimdall to extract it from there by configuring this strategy as follows:\n- body_parameter: access_token Authentication Data Forward Strategy Authentication data strategy defines the way how heimdall should forward the authentication data extracted from the request to the used identity management system.\nAn Authentication Data Forward Strategy configuration entry must contain the following two properties:\ntype - The type of the strategy. Available types are described in the following sections.\nconfig - The strategy specific configuration.\nBody Forward Strategy This strategy can be used to embed the extracted authentication data into a body parameter of the request to the identity management system.\ntype must be set to body. config supports the following properties:\nname: string (mandatory)\nThe name of the property for the authentication data.\nExample 6. Body strategy configuration The following snippet shows how to configure this strategy to send e.g. a token in a property named \u0026#34;idToken\u0026#34;.\ntype: body config: name: idToken Depending on the configured \u0026#34;Content-Type\u0026#34; header for the request (see Endpoint headers) the result might look like\nidToken=\u0026lt;whatever the token value is\u0026gt; if the \u0026#34;Content-Type\u0026#34; header was set to application/x-www-form-urlencoded, or\n{ \u0026#34;idToken\u0026#34;: \u0026#34;\u0026lt;whatever the token value is\u0026gt;\u0026#34; } otherwise\nCookie Forward Strategy This strategy can be used to embed the extracted authentication data into a cookie of the request to the identity management system.\ntype must be set to cookie. config supports the following properties:\nname: string (mandatory)\nThe name of the cookie for the authentication data.\nExample 7. Cookie strategy configuration The following snippet shows how to configure this strategy to send e.g. a token in a cookie named \u0026#34;it_token\u0026#34;.\ntype: cookie config: name: it_token Header Forward Strategy This strategy can be used to embed the extracted authentication data into a header of the request to the identity management system.\ntype must be set to header. config supports the following properties:\nname: string (mandatory)\nThe name of the header for the authentication data.\nscheme: string (optional)\nThe scheme for the header added in front of the authentication data value.\nExample 8. Header strategy configuration The following snippet shows how to configure this strategy to send e.g. a token in a header named \u0026#34;X-ID-Token\u0026#34; with scheme \u0026#34;Bearer\u0026#34;.\ntype: header config: name: X-ID-Token scheme: Bearer Query Forward Strategy This strategy can be used to embed the extracted authentication data into a query parameter of the request to the identity management system.\nUsing this strategy is discouraged, as it will expose the authentication data to access logs, metrics and tracing. type must be set to query. config supports the following properties:\nname: string (mandatory)\nThe name of the query parameter for the authentication data.\nExample 9. Query strategy configuration The following snippet shows how to configure this strategy to send e.g. a token in a query named \u0026#34;token\u0026#34;.\ntype: query config: name: token Authentication Strategy Authentication strategy is kind of abstract type, so you have to define which specific type to use. Each type has its own configuration options.\nAn AuthStrategy configuration entry must contain the following two properties:\ntype - The type of the strategy. Available types are described in the following sections.\nconfig - The strategy specific configuration.\nAvailable strategies are described in the following sections.\nAPI Key Strategy This strategy can be used if your endpoint expects a specific api key be sent in a header, a cookie or query.\ntype must be set to api_key. config supports the following properties:\nin: string (mandatory)\nWhere to put the api key. Can be either header, cookie, or query.\nUsing query strategy will expose the api key to access logs and tracing. name: string (mandatory)\nThe name of either the header or the cookie.\nvalue: string (mandatory)\nThe value of the api key.\nExample 10. API Key Strategy configuration The following snippet shows how to configure this strategy to send an api key in the X-My-API-Key HTTP header.\ntype: api_key config: in: header name: X-My-API-Key value: super-duper-secret-key Basic Auth Strategy This strategy can be used if your endpoint is protected by HTTP basic authentication and expects the HTTP Authorization header with required values.\ntype must be set to basic_auth. config supports the following properties:\nuser: string (mandatory)\nThe user-id.\npassword: string (mandatory)\nThe password.\nExample 11. Basic Auth Strategy configuration The following snippet shows how to configure this strategy with user set to \u0026#34;Alladin\u0026#34; and password set to \u0026#34;open sesame\u0026#34;\ntype: basic_auth config: user: Alladin password: open sesame HTTP Message Signatures This strategy implements HTTP message signatures according to RFC 9421 to sign outbound requests.\ntype must be set to http_message_signatures. config supports the following properties:\nttl: Duration (optional)\nThe TTL of the resulting signature. Defaults to 1m. Responsible for setting created and expires parameters in the resulting signature.\nlabel: string (optional)\nThe label to use. Defaults to sig.\ncomponents: string array (mandatory)\nThe components to be covered by the signature. While the RFC allows for signatures that do not cover any components, this is considered a security risk. When using the \u0026#34;content-digest\u0026#34; component, Heimdall will compute hash values of the request body using sha-256 and sha-512 algorithms. It will then add a Content-Digest header with these hash values to the request, and this header will be included in the signature calculation.\nsigner: Signer (mandatory)\nThe configuration of the key material used for signature creation purposes, as well as the name used for the tag parameter in the resulting signature.\nExample 12. Strategy configuration type: http_message_signatures config: ttl: 2m label: foo components: [\u0026#34;@method\u0026#34;, \u0026#34;content-digest\u0026#34;, \u0026#34;@authority\u0026#34;, \u0026#34;x-my-fancy-header\u0026#34;] signer: name: bar key-store: path: /path/to/key.pem OAuth2 Client Credentials Grant Flow Strategy This strategy implements the OAuth2 Client Credentials Grant Flow to obtain an access token expected by the endpoint. Heimdall caches the received access token.\ntype must be set to oauth2_client_credentials. config supports the following properties:\ntoken_url: string (mandatory)\nThe token endpoint of the authorization server.\nUsage of TLS is enforced as long as heimdall is not started with --insecure-skip-egress-tls-enforcement flag, which allows insecure communication to any of the configured services. client_id: string (mandatory)\nThe client identifier for heimdall.\nclient_secret: string (mandatory)\nThe client secret for heimdall.\nauth_method: string (optional)\nThe authentication method to be used according to RFC 6749, Client Password. Can be one of\nbasic_auth (default if auth_method is not set): With that authentication method, the \u0026#34;application/x-www-form-urlencoded\u0026#34; encoded values of client_id and client_secret are sent to the authorization server via the Authorization header using the Basic scheme.\nrequest_body: With that authentication method the client_id and client_secret are sent in the request body together with the other parameters (e.g. scopes) defined by the flow.\nUsage of request_body authentication method is not recommended and should be avoided. scopes: string array (optional)\nThe scopes required for the access token.\ncache_ttl: Duration (optional)\nHow long to cache the token received from the token endpoint. Defaults to the token expiration information from the token endpoint (the value of the expires_in field) if present. If the token expiration inforation is not present and cache_ttl is not configured, the received token is not cached. If the token expiration information is present in the response and cache_ttl is configured the shorter value is taken. If caching is enabled, the token is cached until 5 seconds before its expiration. To disable caching, set it to 0s. The cache key calculation is based on the values of token_url, client_id, client_secret and the scopes properties.\nheader: object (optional, overridable)\nDefines the name and scheme to be used for the header. Defaults to Authorization with scheme Bearer. If defined, the name property must be set. If scheme is not defined, no scheme will be prepended to the resulting JWT.\nExample 13. Strategy configuration type: oauth2_client_credentials config: header: name: X-My-Token token_url: https://my-auth.provider/token client_id: foo client_secret: bar auth_method: basic_auth ttl: 10m scopes: - baz - zap Authorization Expression Authorization expressions define, as the name implies expressions for authorization purposes and have the following properties:\nexpression string (mandatory)\nThe expression to execute.\nmessage string (optional)\nThe message to include into the error if the expression fails.\nExample 14. Example expression using CEL The expression below determine whether attributes property of a subject object (also shown below) has at least one key that starts with the group prefix, and ensure that all group-like keys have list values containing only strings that end with @acme.co.\nsubject id: \u0026#34;foobar\u0026#34; attributes: group1: [\u0026#34;admin@acme.co\u0026#34;, \u0026#34;analyst@acme.co\u0026#34;] labels: [\u0026#34;metadata\u0026#34;, \u0026#34;prod\u0026#34;, \u0026#34;pii\u0026#34;] groupN: [\u0026#34;forever@acme.co\u0026#34;] expression: | subject.attributes.exists(c, c.startsWith(\u0026#39;group\u0026#39;)) \u0026amp;\u0026amp; subject.attributes .filter(c, c.startsWith(\u0026#39;group\u0026#39;)) .all(c, subject.attributes[c] .all(g, g.endsWith(\u0026#39;@acme.co\u0026#39;))) message: No groups ending with @acme.co present ByteSize ByteSize is actually a string type, which adheres to the following pattern: ^[0-9]+(B|KB|MB)$\nSo with 10B you can define the byte size of 10 bytes and with 2MB you can say 2 megabytes.\nCORS CORS (Cross-Origin Resource Sharing) headers can be added and configured by making use of this type. This functionality allows for advanced security features to quickly be set. If CORS headers are set, then heimdall does not pass preflight requests to its decision pipeline, instead the response will be generated and sent back to the client directly. Following properties are supported:\nallowed_origins: string array (optional)\nList of origins that may access the resource. Defaults to all, if not set, but any of the other CORS options are configured.\nallowed_methods: string array (optional)\nList of methods allowed when accessing the resource. This is used in response to a preflight request. Defaults to GET, POST, HEAD, PUT, DELETE and PATCH if not set, but any of the other CORS options are configured.\nallowed_headers: string array (optional)\nList of request headers that can be used when making the actual request.\nexposed_headers: string array (optional)\n\u0026#34;Allow-List\u0026#34; of headers that clients are allowed to access.\nallow_credentials: boolean (optional)\nIndicates whether the response to the request can be exposed when the credentials flag is true. When used as part of a response to a preflight request, this indicates whether the actual request can be made using credentials. Defaults to false if not set, but any of the other CORS options are configured.\nmax_age: Duration (optional)\nIndicates how long the results of a preflight request can be cached. Defaults to 0 seconds if not set, but any of the other CORS options are configured.\nExample 15. Possible configuration allowed_origins: - example.org allowed_methods: - HEAD - PATCH allow_credentials: true max_age: 10s Duration Duration is actually a string type, which adheres to the following pattern: ^[0-9]+(ns|us|ms|s|m|h)$\nSo with 10s you can define the duration of 10 seconds and with 2h you can say 2 hours.\nEndpoint The Endpoint type defines the properties required for communication with an endpoint.\nIf only the URL needs to be set, you can specify it as a string. If additional properties are required, the following options are available:\nurl string (mandatory)\nThe URL of the endpoint. Depending on the mechanism, the URL can be templated.\nIf templating is used, the user info, scheme, and host parts of the URL cannot be templated. Attempts to do so will result in runtime errors.\nTLS is enforced unless heimdall is started with the --insecure-skip-egress-tls-enforcement flag, which allows insecure communication with any configured service.\nmethod string (optional)\nThe HTTP method to use while communicating with the endpoint. If not set POST is used.\nretry Retry (optional)\nWhat to do if the communication fails. If not configured, no retry attempts are done.\nauth Authentication Strategy (optional)\nAuthentication strategy to apply, if the endpoint requires authentication.\nheaders map of strings (optional)\nHTTP headers to be sent to the endpoint.\nThese headers are not analyzed by heimdall and are just forwarded to the endpoint. E.g. if you configure the Content-Encoding to something like gzip, the service behind the used endpoint might fail to answer, as it would expect the body to be compressed. http_cache object (optional)\nControls whether HTTP caching according to RFC 7234 should be used. To support this, that object defines the following properties:\nenabled boolean (optional)\nDefaults to false if not otherwise stated in the description of the configuration type, making use of the endpoint property. If set to true heimdall will strictly follow the requirements from RFC 7234 and cache the responses if possible and reuse these if still valid.\ncache_ttl Duration (optional)\nSpecifies how long heimdall should cache the response if the endpoint referenced by the URL does not provide any explicit expiration time (no heuristic freshness lifetime is calculated). Without configuring this property, heimdall treats such responses as not cacheable. Defaults to 0s if not otherwise stated in the description of the configuration type making use of the endpoint property.\nExample 16. Endpoint configuration as string https://foo.bar Example 17. Structured Endpoint configuration url: https://foo.bar method: GET retry: give_up_after: 5s max_delay: 1s auth: type: api_key config: name: foo value: bar in: cookie headers: X-My-First-Header: foobar X-My-Second-Header: barfoo http_cache: enabled: true Error/State Type Heimdall defines a couple of error/state types, which it uses to signal errors. Those, which are marked with (*) are available in CEL expressions. All can be used to define overrides for the HTTP response codes.\nFollowing types are available:\naccepted - this is the only state type in this list and is used to signal, the matched decision pipeline has been executed successfully, so the request can be forwarded to the upstream service. The response of that type results by default in a 200 OK response.\nauthentication_error (*) - used if an authenticator failed to verify authentication data available in the request. E.g. an authenticator was configured to verify a JWT and the signature of it was invalid. If none of the authenticators used in a pipeline were able to authenticate the user, and the default error handler was used to handle such error, it will by default result in a 401 Unauthorized response.\nauthorization_error (*) - used if an authorizer failed to authorize the subject. E.g. an authorizer is configured to use an expression on the given subject and request context, but that expression returned with an error. Error of this type results by default in 403 Forbidden response if the default error handler was used to handle such error.\ncommunication_error (*) - this error is used to signal a communication error while communicating to a remote system during the execution of the pipeline of the matched rule. Timeouts of DNSs errors result in such an error. Error of this type results by default in 502 Bad Gateway HTTP code if handled by the default error handler.\ninternal_error - used if heimdall run into an internal error condition while processing the request. E.g. something went wrong while unmarshalling a JSON object, or if there was a configuration error, which couldn’t be raised while loading a rule, etc. Results by default in 500 Internal Server Error response to the caller.\nno_rule_error - this error is used to signal, there is no matching rule to handle the given request. Error of this type results by default in 404 Not Found HTTP code.\nprecondition_error (*) - used if the request does not contain required/expected data. E.g. if an authenticator could not find a cookie configured. Error of this type results by default in 400 Bad Request HTTP code if handled by the default error handler.\nKey Store This type configures a key store holding keys and corresponding certificate chains. PKCS#1, as well as PKCS#8 encodings are supported for private keys.\nWhile loading a key store following verifications are done:\nUniqueness of key ids and rejection of key stores which violate this condition (see also Key-Id Lookup)\nCorrelation of keys and certificates to build a valid certificate chain for every given key if certificates are present. If the correlation fails, an error is raised and heimdall will refuse to start.\nCertificate chain validation. If the chain is invalid, an error is raised and heimdall will refuse to start.\nFollowing configuration properties are available:\npath: string (mandatory)\nThe path to the PEM file with the cryptographic material. Watching for secrets rotation is supported.\npassword: string (optional)\nIf the key material is protected with a password, this property can be set to decipher it. Password protection is only supported for PKCS#8 encoded keys\nIf the key store contains multiple keys and these keys are password protected, same password must be used for all of these. Example 18. Example configuration path: /path/to/keystore.pem password: VeryInsecure! Respond This type enables instructing heimdall to preserve error information and provide it in the response body to the caller, as well as to use HTTP status codes deviating from those heimdall would usually use. The configuration, which can be done using this type affects only the behavior of the default error handler.\nFollowing properties are supported:\nverbose: boolean (optional)\nBy making use of this property you can instruct heimdall to preserve error information and provide it in the response body to the caller. Defaults to false.\nHeimdall supports MIME type negotiation. So, if the client sets the HTTP Accept header to e.g. application/json, and Heimdall run into an unhandled internal error condition, in addition to responding with 500 Internal Server Error, it will render an error message, like shown below, if verbose has been set to true.\n{ \u0026#34;code\u0026#34;: \u0026#34;internal error\u0026#34;, \u0026#34;message\u0026#34;: \u0026#34;whatever led to the error\u0026#34; } The message will however contain just high-level information, like \u0026#34;failed to parse something\u0026#34;, but will not contain any stack traces.\nwith: ResponseOverride set (optional)\nThis property enables mapping between response/error types used by heimdall and the corresponding HTTP status codes. Each entry must be from the list of the supported Error/State Types and contain exactly one property named code, which then defines the desired mapping.\nExample 19. Making error responses verbose and changing the HTTP codes for some errors verbose: true with: authentication_error: code: 404 authorization_error: code: 404 Retry Implements an exponential backoff strategy for endpoint communication. It increases the backoff exponentially by multiplying the max_delay with 2^(attempt count)\ngive_up_after: Duration (optional)\nSets an upper bound on the maximum time to wait between two requests. Default to 0, which means no upper bound.\nmax_delay: Duration (mandatory)\nThe initial backoff.\nExample 20. Retry configuration In this example the backoff will be 1, 2, 4, 8, 16, 32, 60, …​\ngive_up_after: 60s max_delay: 1s Scopes Matcher Scopes matcher is a configuration type allowing configuration of different strategies to match required scopes. In its simplest shape it can be just an array of strings (implemented by the Exact) scope matcher. To cover many use cases, different strategies are available and described in the following sections.\nRegardless of the strategy, each matcher can explicitly be configured and supports the following configuration properties:\nmatching_strategy - the type of the mathing strategy.\nvalues - the list of scope patterns\nExact This the simplest matcher and is automatically selected, if just an array of strings is configured as shown in the following snippet:\n- foo - bar However, as written in the Scopes Matcher section, it can also explicitly be selected by setting matching_strategy to exact and defining the required scopes in the values property.\nExample 21. Essentially same configurations matching_strategy: exact values: - foo - bar - foo - bar Hierarchic This matcher enables matching hierarchical scopes, which use . as separator. Imagine your system is organized that way, that it defines namespaces for different services like this:\nmy-service being the top namespace\nmy-service.booking - being the namespace of the booking service\nmy-service.orders - being the namespace of the orders service\nmy-service.orders.partners - being the namespace of the order service for partners and\nmy-service.orders.customers - being the namespace of the order service for customers\nBasically you’ve established an identity for each of your services (this is comparable to how SPIFFE IDs are organized and also used for).\nNow, imagine you use these namespaces as scope values to limit the usage of the issued tokens. In such situations the hierarchic scope matcher can become handy if you would like to assert any scope of the token must be in e.g. the my-service or the my-service.orders namespace.\nThis matcher can only be used by explicitly setting the matching_strategy to hierarchic and defining the required patterns in the values property.\nExample 22. Matching of hierarchic scopes matching_strategy: hierarchic values: - my-service This configuration will ensure all scopes withing the scope or scp claim are within the my-service namespace. So scope claim like\n{ \u0026#34;scope\u0026#34;: [\u0026#34;my-service.orders\u0026#34;, \u0026#34;my-service.orders.customers\u0026#34;] } would match, but\n{ \u0026#34;scope\u0026#34;: [\u0026#34;not-my-service\u0026#34;, \u0026#34;my-service.orders.customers\u0026#34;] } would not match.\nWildcard This matcher enables matching scopes using wildcards. It goes beyond the Hierarchic scope matcher by enabling usage of wildcards.\nThis matcher can only be used by explicitly setting the matching_strategy to wildcard and defining the required patterns in the values property.\nSession Lifespan This configuration type enables the configuration of session lifespans, used for session validation for those authenticators, which act on non-standard protocols. Following properties are available.\nactive: string (optional)\nA GJSON Path pointing to the field describing the \u0026#34;active\u0026#34; status of the session in the corresponding JSON object. The actual value in that field should be convertable to a bool type. If not provided, or not found in the session object, the session is considered to be \u0026#34;active\u0026#34;. \u0026#34;active\u0026#34; means it can be used and represent a valid session between the authentication system and the subject, the session has been issued to.\nissued_at: string (optional)\nA GJSON Path pointing to the field in the corresponding JSON object, describing the time, when the session object has been issued. If not provided or not found, the issuance time is not considered during session validation.\nnot_before: string (optional)\nA GJSON Path pointing to the field in the corresponding JSON object describing the time, until which the session object is not allowed to be used. If not provided or not found, the corresponding time is not considered during session validation.\nnot_after: string (optional)\nA GJSON Path pointing to the field in the corresponding JSON object describing the time, after which the session object is not allowed to be used. If not provided or not found, the corresponding time is not considered during session validation.\ntime_format: string (optional)\nSince different authentication system use different representations for time strings, this property allows the definition of the time format/layout used by the authentication system. Defaults to Unix Epoch time stamp.\nYou can use the following Go Playground link to test your time format settings. validity_leeway: Duration (optional)\nEnables definition of an allowed time drift between the authentication system and heimdall for the validation of the session validity. Defaults to 0.\nExample 23. Making use of session information received from Ory’s Kratos A typical response from Kratos\u0026#39; whoami endpoint looks like follows (stripped to the most interesting parts):\n{ \u0026#34;id\u0026#34;: \u0026#34;1338410d-c473-4503-a96a-53efa06e2531\u0026#34;, \u0026#34;active\u0026#34;: true, \u0026#34;expires_at\u0026#34;: \u0026#34;2021-10-15T15:58:57.683338Z\u0026#34;, \u0026#34;authenticated_at\u0026#34;: \u0026#34;2021-10-14T15:58:57.683338Z\u0026#34;, \u0026#34;issued_at\u0026#34;: \u0026#34;2021-10-14T15:58:57.683338Z\u0026#34;, \u0026#34;identity\u0026#34;: { \u0026#34;id\u0026#34;: \u0026#34;9496bbd5-f426-473f-b087-c7df853f274a\u0026#34;, ... } } To enable usage of these properties in Heimdall, you can configure the Session Lifespan as follows:\nactive: active issued_at: issued_at not_before: authenticated_at not_after: expires_at time_format: \u0026#34;2006-01-02T15:04:05.999999Z07\u0026#34; validity_leeway: 10s Example 24. Making use of session information received from a compliant OAuth2 authorization service A typical response from a token introspection endpoint looks like follows:\n{ \u0026#34;active\u0026#34;: true, \u0026#34;client_id\u0026#34;: \u0026#34;l238j323ds-23ij4\u0026#34;, \u0026#34;username\u0026#34;: \u0026#34;jdoe\u0026#34;, \u0026#34;scope\u0026#34;: \u0026#34;read write dolphin\u0026#34;, \u0026#34;sub\u0026#34;: \u0026#34;Z5O3upPC88QrAjx00dis\u0026#34;, \u0026#34;aud\u0026#34;: \u0026#34;https://protected.example.net/resource\u0026#34;, \u0026#34;iss\u0026#34;: \u0026#34;https://server.example.com/\u0026#34;, \u0026#34;exp\u0026#34;: 1419356238, \u0026#34;iat\u0026#34;: 1419350238, \u0026#34;extension_field\u0026#34;: \u0026#34;twenty-seven\u0026#34; } To enable usage of these properties in Heimdall, you can configure the Session Lifespan as follows:\nactive: active issued_at: iat not_after: exp validity_leeway: 10s As you see, there is no need to define the time format as the times values appearing in the responses from an introspection endpoint are Unix Epoch time stamps.\nSigner When heimdall is used to issue signed objects, like JWTs, to enable upstream services to rely on authentic information, it acts as an issuer of such objects and requires corresponding configuration.\nFollowing properties are supported:\nname: string (optional)\nThe name used to specify the issuer. E.g. if a JWT is generated, this value is used to set the iss claim. If not set, the value heimdall is used.\nkey_store: Key Store (mandatory)\nThe key store containing the cryptographic material. At least one private key must be present.\nkey_id: string (optional)\nIf the key_store contains multiple keys, this property can be used to specify the key to use (see also Key-Id Lookup). If not specified, the first key is used. If specified, but there is no key for the given key id present, an error is raised and heimdall will refuse to start.\nExample 25. Possible configuration Imagine you have a PEM file located in /opt/heimdall/keystore.pem with the following contents:\n-----BEGIN EC PRIVATE KEY----- X-Key-ID: foo MIGkAgEBBDBRLr783dIM5NHJnDDMRVBiFSF56xqHle5lZk1ZCyyow9wKZGuF4EWK jRBISBkE3NSgBwYFK4EEACKhZANiAAQ+oGUOJpVjntIWuanYxpXe6oN5tKhzLhBX GP1SOXiLhnPNnN2uZu9KwOoBzoZhr/Fxw+sziXmzHJwjluz78VOlFKyopxTfmxRZ 0qq3f/KHWdDtVvmTfT0O/ux9mg6mCJw= -----END EC PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIByjCCAVGgAwIBAgIBATAKBggqhkjOPQQDAzAuMQswCQYDVQQGEwJFVTENMAsG A1UEChMEVGVzdDEQMA4GA1UEAxMHVGVzdCBDQTAeFw0yMjA4MTUwOTE3MTFaFw0y MjA4MTUxMDE3MTFaMDAxCzAJBgNVBAYTAkVVMQ0wCwYDVQQKEwRUZXN0MRIwEAYD VQQDEwlUZXN0IEVFIDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ+oGUOJpVjntIW uanYxpXe6oN5tKhzLhBXGP1SOXiLhnPNnN2uZu9KwOoBzoZhr/Fxw+sziXmzHJwj luz78VOlFKyopxTfmxRZ0qq3f/KHWdDtVvmTfT0O/ux9mg6mCJyjQTA/MA4GA1Ud DwEB/wQEAwIHgDAMBgNVHQ4EBQQDYmFyMB8GA1UdIwQYMBaAFLO77bgPgZMKz11D BVDUXvtNGeBnMAoGCCqGSM49BAMDA2cAMGQCMFRlx9Bq0MuSh5pDhDTqRq/MnxxD W7qZg15AXoNnLrR60vV9gHjzkp1UkcU9viRIuAIwU0BjwDncp9z1seqKh+/eJV3f xstQe2rzUEptWLIiPFoOBWZuw9wJ/Hunjik3a9T/ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIByjCCAVCgAwIBAgIBATAKBggqhkjOPQQDAzAuMQswCQYDVQQGEwJFVTENMAsG A1UEChMEVGVzdDEQMA4GA1UEAxMHVGVzdCBDQTAeFw0yMjA4MTUwOTE3MTFaFw0y MjA4MTYwOTE3MTFaMC4xCzAJBgNVBAYTAkVVMQ0wCwYDVQQKEwRUZXN0MRAwDgYD VQQDEwdUZXN0IENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEf96tstMNdNoNfYjl bGY6BvBFTsl9E3hpPnta7SJn6BqIYz6KEohDJ+8DXwUMVb5Ytr/QkEikg966HCY3 A9TFBUdAs01TV8f2KoAPRQVrh+ccSLLJyACENfZ5VbGSQ0wso0IwQDAOBgNVHQ8B Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUs7vtuA+BkwrPXUMF UNRe+00Z4GcwCgYIKoZIzj0EAwMDaAAwZQIxAMPgE/Z+1Dcj+lH7jioE16Hig0HQ FC4qBx1UU05H05Gs23ECB1hzD2qXikVpaNyuDgIwbogEu42wIwpDa5xdJIZcIhmz DIuPvEscUDjU3C+1GPxmACcRMPv9QVUEcBAvZkfn -----END CERTIFICATE----- Then you can configure heimdall to use it like follows:\nsigner: name: foobar key_store: path: /opt/heimdall/keystore.pem key_id: foo Subject This configuration type enables extraction of subject information from responses received by Heimdall from authentication services. Following properties are available.\nid: string (mandatory)\nA GJSON Path pointing to the id of the subject in the JSON object.\nattributes: string (optional)\nA GJSON Path pointing to the attributes of the subject in the JSON object. Defaults to @this.\nExample 26. Extracting subject id from an OAuth2 Introspection endpoint response. This example shows how to extract the subject id from an OAuth2 Introspection endpoint response and set the subject attributes to the entire response\nid: sub attributes: @this Setting attributes was actually not required, as @this would be set by default anyway.\nExample 27. Extracting subject id from an Ory Kratos \u0026#34;whoami\u0026#34; endpoint response This example shows how to extract the subject id from an Ory Kratos \u0026#34;whoami\u0026#34; endpoint response and set the subject attributes to the entire response. attributes is not configured, so default is used.\nid: identity.id TLS Following are the supported TLS configuration properties:\nkey_store: Key Store (mandatory)\nThe key store containing the cryptographic material. At least one private key and the corresponding certificate must be present.\nkey_id: string (optional)\nIf the key_store contains multiple keys, this property can be used to specify the key to use (see also Key-Id Lookup). If not specified, the first key is used. If specified, but there is no key for the given key id present, an error is raised and heimdall will refuse to start.\nmin_version: string (optional)\nThe minimal TLS version to support. Can be either TLS1.2 or TLS1.3. Defaults to TLS1.3.\ncipher_suites: string array (optional)\nCan be configured if min_version is set to TLS1.2. If min_version is set to TLS1.3 the configured values are ignored. Only the following PFS cipher suites are supported:\nTLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\nTLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\nTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\nTLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\nTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\nTLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\nTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\nTLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\nDefaults to the last six cipher suites if min_version is set to TLS1.2 and cipher_suites is not configured.\nExample 28. Example configuration key_store: path: /path/to/keystore.pem password: VeryInsecure! key_id: foobar min_version: TLS1.2 cipher_suites: - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 Key-Id Lookup When heimdall loads a key store, following algorithm is used to get the key id for the key:\nif the PEM entry with the private key has X-Key-ID header specified, this value is used as key id\nOtherwise, if an X.509 certificate is present for the private key, and it has the Subject Key Identifier extension set, the hex representation of it is used as key id.\nOtherwise, heimdall calculates the value for the Subject Key Identifier according to RFC 3280, Section 4.2.1.2 and uses hex representation of it as key id.\n","description":"","html_content":"\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_assertions\"\u003eAssertions\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis type enables configuration of required token and claim assertions. Depending on the object type (JWT or introspection response), the assertions apply to different parts of such objects.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escopes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_scopes_matcher\"\u003eScopes Matcher\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRequired scopes given to the client.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eaudience\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eValues to be matched in the \u003ccode\u003eaud\u003c/code\u003e claim. This assertion evaluates to \u003ccode\u003etrue\u003c/code\u003e if at least one entry in the given \u003ccode\u003eaudience\u003c/code\u003e array is present in the \u003ccode\u003eaud\u003c/code\u003e claim. Both cases, either as whitespace separated string, or a JSON array are considered.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eissuers\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIssuers to trust.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallowed_algorithms\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAlgorithms, which are trusted (according to \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc7518\"\u003eRFC 7518\u003c/a\u003e). Defaults to the following list: ES256, ES384, ES512, PS256, PS384, PS512.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalidity_leeway\u003c/code\u003e\u003c/strong\u003e \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe time leeway to consider while verifying the \u003ccode\u003eiat\u003c/code\u003e, \u003ccode\u003eexp\u003c/code\u003e and the \u003ccode\u003enbf\u003c/code\u003e. Defaults to 10 seconds.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 1. Assertions configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n\u003cspan class=\"na\"\u003eaudience\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ezap\u003c/span\u003e\n\u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebaz\u003c/span\u003e\n\u003cspan class=\"na\"\u003eallowed_algorithms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eES512\u003c/span\u003e\n\u003cspan class=\"na\"\u003evalidity_leeway\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHere we say, the token must have been issued either by the issuer \u003ccode\u003efoo\u003c/code\u003e, or the issuer \u003ccode\u003ebar\u003c/code\u003e, the \u003ccode\u003eaud\u003c/code\u003e claim must contain \u003ccode\u003ezap\u003c/code\u003e, the scope claim (either \u003ccode\u003escp\u003c/code\u003e or \u003ccode\u003escope\u003c/code\u003e) must be present and contain the scope \u003ccode\u003ebaz\u003c/code\u003e, if the token or the introspection response is signed, it must have been signed by using the \u003ccode\u003eES512\u003c/code\u003e algorithm (ECDSA using P-521 and SHA-512) and if the information about token validity is present, we respect a deviation of 5 seconds.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authentication_data_source\"\u003eAuthentication Data Source\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAn authentication data source is actually a list of possible strategies for subject authentication data retrieval. The entries following the first one are fallbacks and are only executed if the previous strategy could not retrieve the required authentication data from the request.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis fallback mechanism can become handy, if different clients of your application send the authentication data using different methods. \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc6750\"\u003eRFC 6750\u003c/a\u003e describes for example how to use bearer tokens in HTTP requests to access OAuth 2.0 protected resources. This RFC says, a token can either be sent in the \u003ccode\u003eAuthorization\u003c/code\u003e header, or in a query parameter, or even as part of the HTTP body. So you can define the following list to let Heimdall try to extract the access token from all three places:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003equery_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ebody_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe available strategies are described in the following sections.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_cookie_strategy\"\u003eCookie Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can retrieve authentication data from a specific HTTP cookie. Following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecookie\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the cookie to use.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 2. Cookie Strategy usage\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you want Heimdall to verify an authentication session, which is represented by a specific cookie before the request hits your upstream service. If the client of your upstream application, which is case of a cookie would usually be a browser sends a cookie named \u0026#34;session\u0026#34;, you can inform Heimdall to extract and use it by configuring this strategy as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ecookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy_session_cookie\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_header_strategy\"\u003eHeader Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can retrieve authentication data from a specific HTTP header. Following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheader\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the header to use.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escheme\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eScheme, which should be present in the header value. If specified, but not present in the header value, the authentication data cannot be retrieved, effectively making the affected authenticator feel not responsible for the request.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 3. Header Strategy usage\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the HTTP \u003ccode\u003eAuthorization\u003c/code\u003e header, you can inform Heimdall to extract it from there by configuring this strategy as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_query_parameter_strategy\"\u003eQuery Parameter Strategy\u003c/h3\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003equery_parameter\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the query parameter to use.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 4. Query Parameter Strategy usage\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the query parameter named \u0026#34;access_token\u0026#34;, you can inform Heimdall to extract it from there by configuring this strategy as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003equery_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_body_parameter_strategy\"\u003eBody Parameter Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe usage of this strategy is only possible when the request payload is either JSON or \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e encoded. The \u003ccode\u003eContent-Type\u003c/code\u003e of the request must also either be set to \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e or to a MIME type, which contains \u003ccode\u003ejson\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ebody_parameter\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the body parameter to use.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 5. Body Parameter Strategy usage\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you want Heimdall to verify an access token used to protect your upstream service. If the client of your upstream application sends the access token in the body parameter named \u0026#34;access_token\u0026#34;, you can inform Heimdall to extract it from there by configuring this strategy as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ebody_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authentication_data_forward_strategy\"\u003eAuthentication Data Forward Strategy\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAuthentication data strategy defines the way how heimdall should forward the authentication data extracted from the request to the used identity management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAn Authentication Data Forward Strategy configuration entry must contain the following two properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e - The type of the strategy. Available types are described in the following sections.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003econfig\u003c/code\u003e - The strategy specific configuration.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_body_forward_strategy\"\u003eBody Forward Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used to embed the extracted authentication data into a body parameter of the request to the identity management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003ebody\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the property for the authentication data.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 6. Body strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy to send e.g. a token in a property named \u0026#34;idToken\u0026#34;.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebody\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eidToken\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDepending on the configured \u0026#34;Content-Type\u0026#34; header for the request (see \u003ca href=\"#_endpoint\"\u003e\u003ccode\u003eEndpoint\u003c/code\u003e\u003c/a\u003e \u003ccode\u003eheaders\u003c/code\u003e) the result might look like\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003eidToken=\u0026lt;whatever the token value is\u0026gt;\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eif the \u0026#34;Content-Type\u0026#34; header was set to \u003ccode\u003eapplication/x-www-form-urlencoded\u003c/code\u003e, or\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;idToken\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u0026lt;whatever the token value is\u0026gt;\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eotherwise\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_cookie_forward_strategy\"\u003eCookie Forward Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used to embed the extracted authentication data into a cookie of the request to the identity management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003ecookie\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the cookie for the authentication data.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 7. Cookie strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy to send e.g. a token in a cookie named \u0026#34;it_token\u0026#34;.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecookie\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eit_token\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_header_forward_strategy\"\u003eHeader Forward Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used to embed the extracted authentication data into a header of the request to the identity management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003eheader\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the header for the authentication data.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escheme\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe scheme for the header added in front of the authentication data value.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 8. Header strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy to send e.g. a token in a header named \u0026#34;X-ID-Token\u0026#34; with scheme \u0026#34;Bearer\u0026#34;.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-ID-Token\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_query_forward_strategy\"\u003eQuery Forward Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used to embed the extracted authentication data into a query parameter of the request to the identity management system.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsing this strategy is discouraged, as it will expose the authentication data to access logs, metrics and tracing.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003equery\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of the query parameter for the authentication data.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 9. Query strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy to send e.g. a token in a query named \u0026#34;token\u0026#34;.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003equery\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etoken\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authentication_strategy\"\u003eAuthentication Strategy\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAuthentication strategy is kind of abstract type, so you have to define which specific type to use. Each type has its own configuration options.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAn AuthStrategy configuration entry must contain the following two properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e - The type of the strategy. Available types are described in the following sections.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003econfig\u003c/code\u003e - The strategy specific configuration.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAvailable strategies are described in the following sections.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_api_key_strategy\"\u003eAPI Key Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used if your endpoint expects a specific api key be sent in a header, a cookie or query.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003eapi_key\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ein\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhere to put the api key. Can be either \u003ccode\u003eheader\u003c/code\u003e, \u003ccode\u003ecookie\u003c/code\u003e, or \u003ccode\u003equery\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsing \u003ccode\u003equery\u003c/code\u003e strategy will expose the api key to access logs and tracing.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name of either the header or the cookie.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalue\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe value of the api key.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 10. API Key Strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy to send an api key in the \u003ccode\u003eX-My-API-Key\u003c/code\u003e HTTP header.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-My-API-Key\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esuper-duper-secret-key\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_basic_auth_strategy\"\u003eBasic Auth Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy can be used if your endpoint is protected by HTTP basic authentication and expects the HTTP \u003ccode\u003eAuthorization\u003c/code\u003e header with required values.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003ebasic_auth\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003euser\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe user-id.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epassword\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe password.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 11. Basic Auth Strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe following snippet shows how to configure this strategy with user set to \u0026#34;Alladin\u0026#34; and password set to \u0026#34;open sesame\u0026#34;\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAlladin\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eopen sesame\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_http_message_signatures\"\u003eHTTP Message Signatures\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy implements HTTP message signatures according to \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc9421\"\u003eRFC 9421\u003c/a\u003e to sign outbound requests.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003ehttp_message_signatures\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ettl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe TTL of the resulting signature. Defaults to 1m. Responsible for setting \u003ccode\u003ecreated\u003c/code\u003e and \u003ccode\u003eexpires\u003c/code\u003e parameters in the resulting signature.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003elabel\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe label to use. Defaults to \u003ccode\u003esig\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecomponents\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe components to be covered by the signature. While the RFC allows for signatures that do not cover any components, this is considered a security risk. When using the \u003ccode\u003e\u0026#34;content-digest\u0026#34;\u003c/code\u003e component, Heimdall will compute hash values of the request body using \u003ccode\u003esha-256\u003c/code\u003e and \u003ccode\u003esha-512\u003c/code\u003e algorithms. It will then add a \u003ccode\u003eContent-Digest\u003c/code\u003e header with these hash values to the request, and this header will be included in the signature calculation.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003esigner\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_signer\"\u003eSigner\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe configuration of the key material used for signature creation purposes, as well as the name used for the \u003ccode\u003etag\u003c/code\u003e parameter in the resulting signature.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 12. Strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttp_message_signatures\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2m\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecomponents\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@method\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003econtent-digest\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@authority\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ex-my-fancy-header\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey-store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/key.pem\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_oauth2_client_credentials_grant_flow_strategy\"\u003eOAuth2 Client Credentials Grant Flow Strategy\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis strategy implements the \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc6749#section-4.4\"\u003eOAuth2 Client Credentials Grant Flow\u003c/a\u003e to obtain an access token expected by the endpoint. Heimdall caches the received access token.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ccode\u003etype\u003c/code\u003e must be set to \u003ccode\u003eoauth2_client_credentials\u003c/code\u003e. \u003ccode\u003econfig\u003c/code\u003e supports the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etoken_url\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe token endpoint of the authorization server.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsage of TLS is enforced as long as heimdall is not started with \u003ccode\u003e--insecure-skip-egress-tls-enforcement\u003c/code\u003e flag, which allows insecure communication to any of the configured services.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclient_id\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe client identifier for heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eclient_secret\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe client secret for heimdall.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauth_method\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe authentication method to be used according to \u003ca href=\"https://www.rfc-editor.org/rfc/rfc6749#section-2.3.1\"\u003eRFC 6749, Client Password\u003c/a\u003e. Can be one of\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ebasic_auth\u003c/code\u003e (default if \u003ccode\u003eauth_method\u003c/code\u003e is not set): With that authentication method, the \u003ccode\u003e\u0026#34;application/x-www-form-urlencoded\u0026#34;\u003c/code\u003e encoded values of \u003ccode\u003eclient_id\u003c/code\u003e and \u003ccode\u003eclient_secret\u003c/code\u003e are sent to the authorization server via the \u003ccode\u003eAuthorization\u003c/code\u003e header using the \u003ccode\u003eBasic\u003c/code\u003e scheme.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003erequest_body\u003c/code\u003e: With that authentication method the \u003ccode\u003eclient_id\u003c/code\u003e and \u003ccode\u003eclient_secret\u003c/code\u003e are sent in the request body together with the other parameters (e.g. \u003ccode\u003escopes\u003c/code\u003e) defined by the flow.\u003c/p\u003e\n\u003cdiv class=\"admonitionblock warning\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-warning\" title=\"Warning\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nUsage of \u003ccode\u003erequest_body\u003c/code\u003e authentication method is not recommended and should be avoided.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003escopes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe scopes required for the access token.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHow long to cache the token received from the token endpoint. Defaults to the token expiration information from the token endpoint (the value of the \u003ccode\u003eexpires_in\u003c/code\u003e field) if present. If the token expiration inforation is not present and \u003ccode\u003ecache_ttl\u003c/code\u003e is not configured, the received token is not cached. If the token expiration information is present in the response and \u003ccode\u003ecache_ttl\u003c/code\u003e is configured the shorter value is taken. If caching is enabled, the token is cached until 5 seconds before its expiration. To disable caching, set it to \u003ccode\u003e0s\u003c/code\u003e. The cache key calculation is based on the values of \u003ccode\u003etoken_url\u003c/code\u003e, \u003ccode\u003eclient_id\u003c/code\u003e, \u003ccode\u003eclient_secret\u003c/code\u003e and the \u003ccode\u003escopes\u003c/code\u003e properties.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheader\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eobject\u003c/em\u003e (optional, overridable)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefines the \u003ccode\u003ename\u003c/code\u003e and \u003ccode\u003escheme\u003c/code\u003e to be used for the header. Defaults to \u003ccode\u003eAuthorization\u003c/code\u003e with scheme \u003ccode\u003eBearer\u003c/code\u003e. If defined, the \u003ccode\u003ename\u003c/code\u003e property must be set. If \u003ccode\u003escheme\u003c/code\u003e is not defined, no scheme will be prepended to the resulting JWT.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 13. Strategy configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_client_credentials\u003c/span\u003e\n\u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-My-Token\u003c/span\u003e\n \u003cspan class=\"na\"\u003etoken_url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://my-auth.provider/token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_secret\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_method\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10m\u003c/span\u003e\n \u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebaz\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ezap\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_authorization_expression\"\u003eAuthorization Expression\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAuthorization expressions define, as the name implies expressions for authorization purposes and have the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/strong\u003e \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe expression to execute.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emessage\u003c/code\u003e\u003c/strong\u003e \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe message to include into the error if the expression fails.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 14. Example expression using \u003ca href=\"https://github.com/google/cel-spec\"\u003eCEL\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe expression below determine whether \u003ccode\u003eattributes\u003c/code\u003e property of a \u003ccode\u003esubject\u003c/code\u003e object (also shown below) has at least one key that starts with the \u003ccode\u003egroup\u003c/code\u003e prefix, and ensure that all group-like keys have list values containing only strings that end with \u003ccode\u003e@acme.co\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"title\"\u003esubject\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003efoobar\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egroup1\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eadmin@acme.co\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eanalyst@acme.co\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003elabels\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003emetadata\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eprod\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003epii\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e]\u003c/span\u003e\n \u003cspan class=\"na\"\u003egroupN\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eforever@acme.co\u0026#34;\u003c/span\u003e\u003cspan class=\"pi\"\u003e]\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003esubject.attributes.exists(c, c.startsWith(\u0026#39;group\u0026#39;)) \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003esubject.attributes\u003c/span\u003e\n \u003cspan class=\"s\"\u003e.filter(c, c.startsWith(\u0026#39;group\u0026#39;))\u003c/span\u003e\n \u003cspan class=\"s\"\u003e.all(c, subject.attributes[c]\u003c/span\u003e\n \u003cspan class=\"s\"\u003e.all(g, g.endsWith(\u0026#39;@acme.co\u0026#39;)))\u003c/span\u003e\n\u003cspan class=\"na\"\u003emessage\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eNo groups ending with @acme.co present\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_bytesize\"\u003eByteSize\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eByteSize is actually a string type, which adheres to the following pattern: \u003ccode\u003e^[0-9]+(B|KB|MB)$\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSo with \u003ccode\u003e10B\u003c/code\u003e you can define the byte size of 10 bytes and with \u003ccode\u003e2MB\u003c/code\u003e you can say 2 megabytes.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_cors\"\u003eCORS\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS\"\u003eCORS\u003c/a\u003e (Cross-Origin Resource Sharing) headers can be added and configured by making use of this type. This functionality allows for advanced security features to quickly be set. If CORS headers are set, then heimdall does not pass preflight requests to its decision pipeline, instead the response will be generated and sent back to the client directly. Following properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallowed_origins\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eList of origins that may access the resource. Defaults to all, if not set, but any of the other CORS options are configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallowed_methods\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eList of methods allowed when accessing the resource. This is used in response to a preflight request. Defaults to \u003ccode\u003eGET\u003c/code\u003e, \u003ccode\u003ePOST\u003c/code\u003e, \u003ccode\u003eHEAD\u003c/code\u003e, \u003ccode\u003ePUT\u003c/code\u003e, \u003ccode\u003eDELETE\u003c/code\u003e and \u003ccode\u003ePATCH\u003c/code\u003e if not set, but any of the other CORS options are configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallowed_headers\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eList of request headers that can be used when making the actual request.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eexposed_headers\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003e\u0026#34;Allow-List\u0026#34; of headers that clients are allowed to access.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eallow_credentials\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIndicates whether the response to the request can be exposed when the credentials flag is true. When used as part of a response to a preflight request, this indicates whether the actual request can be made using credentials. Defaults to \u003ccode\u003efalse\u003c/code\u003e if not set, but any of the other CORS options are configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_age\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIndicates how long the results of a preflight request can be cached. Defaults to 0 seconds if not set, but any of the other CORS options are configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 15. Possible configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eallowed_origins\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eexample.org\u003c/span\u003e\n\u003cspan class=\"na\"\u003eallowed_methods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eHEAD\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePATCH\u003c/span\u003e\n\u003cspan class=\"na\"\u003eallow_credentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\u003cspan class=\"na\"\u003emax_age\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_duration\"\u003eDuration\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDuration is actually a string type, which adheres to the following pattern: \u003ccode\u003e^[0-9]+(ns|us|ms|s|m|h)$\u003c/code\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSo with \u003ccode\u003e10s\u003c/code\u003e you can define the duration of 10 seconds and with \u003ccode\u003e2h\u003c/code\u003e you can say 2 hours.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_endpoint\"\u003eEndpoint\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ccode\u003eEndpoint\u003c/code\u003e type defines the properties required for communication with an endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf only the URL needs to be set, you can specify it as a string. If additional properties are required, the following options are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eurl\u003c/code\u003e\u003c/strong\u003e \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe URL of the endpoint. Depending on the mechanism, the URL can be templated.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIf templating is used, the user info, scheme, and host parts of the URL cannot be templated. Attempts to do so will result in runtime errors.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eTLS is enforced unless heimdall is started with the \u003ccode\u003e--insecure-skip-egress-tls-enforcement\u003c/code\u003e flag, which allows insecure communication with any configured service.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emethod\u003c/code\u003e\u003c/strong\u003e \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe HTTP method to use while communicating with the endpoint. If not set \u003ccode\u003ePOST\u003c/code\u003e is used.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eretry\u003c/code\u003e\u003c/strong\u003e \u003cem\u003e\u003ca href=\"#_retry\"\u003eRetry\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhat to do if the communication fails. If not configured, no retry attempts are done.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eauth\u003c/code\u003e\u003c/strong\u003e \u003cem\u003e\u003ca href=\"#_authentication_strategy\"\u003eAuthentication Strategy\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAuthentication strategy to apply, if the endpoint requires authentication.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eheaders\u003c/code\u003e\u003c/strong\u003e \u003cem\u003emap of strings\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHTTP headers to be sent to the endpoint.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nThese headers are not analyzed by heimdall and are just forwarded to the endpoint. E.g. if you configure the \u003ccode\u003eContent-Encoding\u003c/code\u003e to something like \u003ccode\u003egzip\u003c/code\u003e, the service behind the used endpoint might fail to answer, as it would expect the body to be compressed.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ehttp_cache\u003c/code\u003e\u003c/strong\u003e \u003cem\u003eobject\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eControls whether HTTP caching according to \u003ca href=\"https://www.rfc-editor.org/rfc/rfc7234\"\u003eRFC 7234\u003c/a\u003e should be used. To support this, that object defines the following properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eenabled\u003c/code\u003e\u003c/strong\u003e \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefaults to \u003ccode\u003efalse\u003c/code\u003e if not otherwise stated in the description of the configuration type, making use of the \u003ccode\u003eendpoint\u003c/code\u003e property. If set to \u003ccode\u003etrue\u003c/code\u003e heimdall will strictly follow the requirements from RFC 7234 and cache the responses if possible and reuse these if still valid.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecache_ttl\u003c/code\u003e\u003c/strong\u003e \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSpecifies how long heimdall should cache the response if the endpoint referenced by the URL does not provide any explicit expiration time (no heuristic freshness lifetime is calculated). Without configuring this property, heimdall treats such responses as not cacheable. Defaults to \u003ccode\u003e0s\u003c/code\u003e if not otherwise stated in the description of the configuration type making use of the \u003ccode\u003eendpoint\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 16. Endpoint configuration as string\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"text\"\u003ehttps://foo.bar\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 17. Structured Endpoint configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar\u003c/span\u003e\n\u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n\u003cspan class=\"na\"\u003eretry\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1s\u003c/span\u003e\n\u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecookie\u003c/span\u003e\n\u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eX-My-First-Header\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\n \u003cspan class=\"na\"\u003eX-My-Second-Header\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebarfoo\u003c/span\u003e\n\u003cspan class=\"na\"\u003ehttp_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_errorstate_type\"\u003eError/State Type\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall defines a couple of error/state types, which it uses to signal errors. Those, which are marked with (*) are available in CEL expressions. All can be used to define overrides for the HTTP response codes.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing types are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eaccepted\u003c/code\u003e - this is the only state type in this list and is used to signal, the matched decision pipeline has been executed successfully, so the request can be forwarded to the upstream service. The response of that type results by default in a \u003ccode\u003e200 OK\u003c/code\u003e response.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eauthentication_error\u003c/code\u003e (*) - used if an authenticator failed to verify authentication data available in the request. E.g. an authenticator was configured to verify a JWT and the signature of it was invalid. If none of the authenticators used in a pipeline were able to authenticate the user, and the default error handler was used to handle such error, it will by default result in a \u003ccode\u003e401 Unauthorized\u003c/code\u003e response.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eauthorization_error\u003c/code\u003e (*) - used if an authorizer failed to authorize the subject. E.g. an authorizer is configured to use an expression on the given subject and request context, but that expression returned with an error. Error of this type results by default in \u003ccode\u003e403 Forbidden\u003c/code\u003e response if the default error handler was used to handle such error.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ecommunication_error\u003c/code\u003e (*) - this error is used to signal a communication error while communicating to a remote system during the execution of the pipeline of the matched rule. Timeouts of DNSs errors result in such an error. Error of this type results by default in \u003ccode\u003e502 Bad Gateway\u003c/code\u003e HTTP code if handled by the default error handler.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003einternal_error\u003c/code\u003e - used if heimdall run into an internal error condition while processing the request. E.g. something went wrong while unmarshalling a JSON object, or if there was a configuration error, which couldn’t be raised while loading a rule, etc. Results by default in \u003ccode\u003e500 Internal Server Error\u003c/code\u003e response to the caller.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eno_rule_error\u003c/code\u003e - this error is used to signal, there is no matching rule to handle the given request. Error of this type results by default in \u003ccode\u003e404 Not Found\u003c/code\u003e HTTP code.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eprecondition_error\u003c/code\u003e (*) - used if the request does not contain required/expected data. E.g. if an authenticator could not find a cookie configured. Error of this type results by default in \u003ccode\u003e400 Bad Request\u003c/code\u003e HTTP code if handled by the default error handler.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_key_store\"\u003eKey Store\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis type configures a key store holding keys and corresponding certificate chains. PKCS#1, as well as PKCS#8 encodings are supported for private keys.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhile loading a key store following verifications are done:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"olist arabic\"\u003e\n\u003col class=\"arabic\"\u003e\n\u003cli\u003e\n\u003cp\u003eUniqueness of key ids and rejection of key stores which violate this condition (see also \u003ca href=\"#_key_id_lookup\"\u003eKey-Id Lookup\u003c/a\u003e)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCorrelation of keys and certificates to build a valid certificate chain for every given key if certificates are present. If the correlation fails, an error is raised and heimdall will refuse to start.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eCertificate chain validation. If the chain is invalid, an error is raised and heimdall will refuse to start.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing configuration properties are available:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epath\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe path to the PEM file with the cryptographic material. Watching for secrets rotation is supported.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003epassword\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the key material is protected with a password, this property can be set to decipher it. Password protection is only supported for PKCS#8 encoded keys\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock caution\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-caution\" title=\"Caution\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nIf the key store contains multiple keys and these keys are password protected, same password must be used for all of these.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 18. Example configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/keystore.pem\u003c/span\u003e\n\u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVeryInsecure!\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_respond\"\u003eRespond\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis type enables instructing heimdall to preserve error information and provide it in the response body to the caller, as well as to use HTTP status codes deviating from those heimdall would usually use. The configuration, which can be done using this type affects only the behavior of the default error handler.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003everbose\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eboolean\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBy making use of this property you can instruct heimdall to preserve error information and provide it in the response body to the caller. Defaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHeimdall supports MIME type negotiation. So, if the client sets the HTTP \u003ccode\u003eAccept\u003c/code\u003e header to e.g. \u003ccode\u003eapplication/json\u003c/code\u003e, and Heimdall run into an unhandled internal error condition, in addition to responding with \u003ccode\u003e500 Internal Server Error\u003c/code\u003e, it will render an error message, like shown below, if \u003ccode\u003everbose\u003c/code\u003e has been set to \u003ccode\u003etrue\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;code\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;internal error\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;whatever led to the error\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe \u003ccode\u003emessage\u003c/code\u003e will however contain just high-level information, like \u0026#34;failed to parse something\u0026#34;, but will not contain any stack traces.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ewith\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003eResponseOverride set\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis property enables mapping between response/error types used by heimdall and the corresponding HTTP status codes. Each entry must be from the list of the supported \u003ca href=\"#_errorstate_type\"\u003eError/State Types\u003c/a\u003e and contain exactly one property named \u003ccode\u003ecode\u003c/code\u003e, which then defines the desired mapping.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 19. Making error responses verbose and changing the HTTP codes for some errors\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003everbose\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\u003cspan class=\"na\"\u003ewith\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e404\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e404\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_retry\"\u003eRetry\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImplements an exponential backoff strategy for endpoint communication. It increases the backoff exponentially by multiplying the \u003ccode\u003emax_delay\u003c/code\u003e with 2^(attempt count)\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003egive_up_after\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSets an upper bound on the maximum time to wait between two requests. Default to 0, which means no upper bound.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emax_delay\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe initial backoff.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 20. Retry configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIn this example the backoff will be 1, 2, 4, 8, 16, 32, 60, …​\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e60s\u003c/span\u003e\n\u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_scopes_matcher\"\u003eScopes Matcher\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eScopes matcher is a configuration type allowing configuration of different strategies to match required scopes. In its simplest shape it can be just an array of strings (implemented by the \u003ca href=\"#_exact\"\u003eExact\u003c/a\u003e) scope matcher. To cover many use cases, different strategies are available and described in the following sections.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eRegardless of the strategy, each matcher can explicitly be configured and supports the following configuration properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003ematching_strategy\u003c/code\u003e - the type of the mathing strategy.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003evalues\u003c/code\u003e - the list of scope patterns\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_exact\"\u003eExact\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis the simplest matcher and is automatically selected, if just an array of strings is configured as shown in the following snippet:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n\u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eHowever, as written in the \u003ca href=\"#_scopes_matcher\"\u003eScopes Matcher\u003c/a\u003e section, it can also explicitly be selected by setting \u003ccode\u003ematching_strategy\u003c/code\u003e to \u003ccode\u003eexact\u003c/code\u003e and defining the required scopes in the \u003ccode\u003evalues\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 21. Essentially same configurations\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ematching_strategy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexact\u003c/span\u003e\n\u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_hierarchic\"\u003eHierarchic\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis matcher enables matching hierarchical scopes, which use \u003ccode\u003e.\u003c/code\u003e as separator. Imagine your system is organized that way, that it defines namespaces for different services like this:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emy-service\u003c/code\u003e being the top namespace\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emy-service.booking\u003c/code\u003e - being the namespace of the booking service\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emy-service.orders\u003c/code\u003e - being the namespace of the orders service\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emy-service.orders.partners\u003c/code\u003e - being the namespace of the order service for partners and\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003emy-service.orders.customers\u003c/code\u003e - being the namespace of the order service for customers\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBasically you’ve established an identity for each of your services (this is comparable to how \u003ca href=\"https://spiffe.io/docs/latest/spiffe-about/spiffe-concepts/#spiffe-id\"\u003eSPIFFE IDs\u003c/a\u003e are organized and also used for).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eNow, imagine you use these namespaces as scope values to limit the usage of the issued tokens. In such situations the hierarchic scope matcher can become handy if you would like to assert any scope of the token must be in e.g. the \u003ccode\u003emy-service\u003c/code\u003e or the \u003ccode\u003emy-service.orders\u003c/code\u003e namespace.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis matcher can only be used by explicitly setting the \u003ccode\u003ematching_strategy\u003c/code\u003e to \u003ccode\u003ehierarchic\u003c/code\u003e and defining the required patterns in the \u003ccode\u003evalues\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 22. Matching of hierarchic scopes\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ematching_strategy\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehierarchic\u003c/span\u003e\n\u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003emy-service\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis configuration will ensure all scopes withing the scope or scp claim are within the \u003ccode\u003emy-service\u003c/code\u003e namespace. So scope claim like\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;scope\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;my-service.orders\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;my-service.orders.customers\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ewould match, but\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;scope\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;not-my-service\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;my-service.orders.customers\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003ewould not match.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect2\"\u003e\n\u003ch3 id=\"_wildcard\"\u003eWildcard\u003c/h3\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis matcher enables matching scopes using wildcards. It goes beyond the \u003ca href=\"#_hierarchic\"\u003eHierarchic\u003c/a\u003e scope matcher by enabling usage of wildcards.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis matcher can only be used by explicitly setting the \u003ccode\u003ematching_strategy\u003c/code\u003e to \u003ccode\u003ewildcard\u003c/code\u003e and defining the required patterns in the \u003ccode\u003evalues\u003c/code\u003e property.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_session_lifespan\"\u003eSession Lifespan\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis configuration type enables the configuration of session lifespans, used for session validation for those authenticators, which act on non-standard protocols. Following properties are available.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eactive\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the field describing the \u0026#34;active\u0026#34; status of the session in the corresponding JSON object. The actual value in that field should be convertable to a \u003ccode\u003ebool\u003c/code\u003e type. If not provided, or not found in the session object, the session is considered to be \u0026#34;active\u0026#34;. \u0026#34;active\u0026#34; means it can be used and represent a valid session between the authentication system and the subject, the session has been issued to.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eissued_at\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the field in the corresponding JSON object, describing the time, when the session object has been issued. If not provided or not found, the issuance time is not considered during session validation.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003enot_before\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the field in the corresponding JSON object describing the time, until which the session object is not allowed to be used. If not provided or not found, the corresponding time is not considered during session validation.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003enot_after\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the field in the corresponding JSON object describing the time, after which the session object is not allowed to be used. If not provided or not found, the corresponding time is not considered during session validation.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003etime_format\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSince different authentication system use different representations for time strings, this property allows the definition of the \u003ca href=\"https://pkg.go.dev/time#pkg-constants\"\u003etime format/layout\u003c/a\u003e used by the authentication system. Defaults to Unix Epoch time stamp.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"admonitionblock note\"\u003e\n\u003ctable\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd class=\"icon\"\u003e\n\u003ci class=\"fa icon-note\" title=\"Note\"\u003e\u003c/i\u003e\n\u003c/td\u003e\n\u003ctd class=\"content\"\u003e\nYou can use the following \u003ca href=\"https://go.dev/play/p/VjtvWMmp-Ua\"\u003eGo Playground\u003c/a\u003e link to test your time format settings.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003evalidity_leeway\u003c/code\u003e\u003c/strong\u003e: \u003ca href=\"#_duration\"\u003eDuration\u003c/a\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eEnables definition of an allowed time drift between the authentication system and heimdall for the validation of the session validity. Defaults to 0.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 23. Making use of session information received from Ory’s Kratos\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA typical response from Kratos\u0026#39; \u003ccode\u003ewhoami\u003c/code\u003e endpoint looks like follows (stripped to the most interesting parts):\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;1338410d-c473-4503-a96a-53efa06e2531\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;active\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;expires_at\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;2021-10-15T15:58:57.683338Z\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;authenticated_at\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;2021-10-14T15:58:57.683338Z\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;issued_at\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;2021-10-14T15:58:57.683338Z\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;identity\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;9496bbd5-f426-473f-b087-c7df853f274a\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"err\"\u003e...\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable usage of these properties in Heimdall, you can configure the Session Lifespan as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eactive\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eactive\u003c/span\u003e\n\u003cspan class=\"na\"\u003eissued_at\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eissued_at\u003c/span\u003e\n\u003cspan class=\"na\"\u003enot_before\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticated_at\u003c/span\u003e\n\u003cspan class=\"na\"\u003enot_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexpires_at\u003c/span\u003e\n\u003cspan class=\"na\"\u003etime_format\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e2006-01-02T15:04:05.999999Z07\u0026#34;\u003c/span\u003e\n\u003cspan class=\"na\"\u003evalidity_leeway\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 24. Making use of session information received from a compliant OAuth2 authorization service\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA typical response from a token \u003ccode\u003eintrospection\u003c/code\u003e endpoint looks like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"json\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;active\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;client_id\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;l238j323ds-23ij4\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;username\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;jdoe\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;scope\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;read write dolphin\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;sub\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Z5O3upPC88QrAjx00dis\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;aud\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://protected.example.net/resource\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;iss\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;https://server.example.com/\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;exp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1419356238\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;iat\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1419350238\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"nl\"\u003e\u0026#34;extension_field\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;twenty-seven\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eTo enable usage of these properties in Heimdall, you can configure the Session Lifespan as follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eactive\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eactive\u003c/span\u003e\n\u003cspan class=\"na\"\u003eissued_at\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eiat\u003c/span\u003e\n\u003cspan class=\"na\"\u003enot_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eexp\u003c/span\u003e\n\u003cspan class=\"na\"\u003evalidity_leeway\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10s\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eAs you see, there is no need to define the time format as the times values appearing in the responses from an introspection endpoint are Unix Epoch time stamps.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_signer\"\u003eSigner\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhen heimdall is used to issue signed objects, like JWTs, to enable upstream services to rely on authentic information, it acts as an issuer of such objects and requires corresponding configuration.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing properties are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe name used to specify the issuer. E.g. if a JWT is generated, this value is used to set the \u003ccode\u003eiss\u003c/code\u003e claim. If not set, the value \u003ccode\u003eheimdall\u003c/code\u003e is used.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ekey_store\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"/docs/configuration/types/#_key_store\"\u003eKey Store\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe key store containing the cryptographic material. At least one private key must be present.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ekey_id\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003ekey_store\u003c/code\u003e contains multiple keys, this property can be used to specify the key to use (see also \u003ca href=\"/docs/configuration/types/#_key_id_lookup\"\u003eKey-Id Lookup\u003c/a\u003e). If not specified, the first key is used. If specified, but there is no key for the given key id present, an error is raised and heimdall will refuse to start.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 25. Possible configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eImagine you have a PEM file located in \u003ccode\u003e/opt/heimdall/keystore.pem\u003c/code\u003e with the following contents:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"txt\"\u003e-----BEGIN EC PRIVATE KEY-----\nX-Key-ID: foo\n\nMIGkAgEBBDBRLr783dIM5NHJnDDMRVBiFSF56xqHle5lZk1ZCyyow9wKZGuF4EWK\njRBISBkE3NSgBwYFK4EEACKhZANiAAQ+oGUOJpVjntIWuanYxpXe6oN5tKhzLhBX\nGP1SOXiLhnPNnN2uZu9KwOoBzoZhr/Fxw+sziXmzHJwjluz78VOlFKyopxTfmxRZ\n0qq3f/KHWdDtVvmTfT0O/ux9mg6mCJw=\n-----END EC PRIVATE KEY-----\n-----BEGIN CERTIFICATE-----\nMIIByjCCAVGgAwIBAgIBATAKBggqhkjOPQQDAzAuMQswCQYDVQQGEwJFVTENMAsG\nA1UEChMEVGVzdDEQMA4GA1UEAxMHVGVzdCBDQTAeFw0yMjA4MTUwOTE3MTFaFw0y\nMjA4MTUxMDE3MTFaMDAxCzAJBgNVBAYTAkVVMQ0wCwYDVQQKEwRUZXN0MRIwEAYD\nVQQDEwlUZXN0IEVFIDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ+oGUOJpVjntIW\nuanYxpXe6oN5tKhzLhBXGP1SOXiLhnPNnN2uZu9KwOoBzoZhr/Fxw+sziXmzHJwj\nluz78VOlFKyopxTfmxRZ0qq3f/KHWdDtVvmTfT0O/ux9mg6mCJyjQTA/MA4GA1Ud\nDwEB/wQEAwIHgDAMBgNVHQ4EBQQDYmFyMB8GA1UdIwQYMBaAFLO77bgPgZMKz11D\nBVDUXvtNGeBnMAoGCCqGSM49BAMDA2cAMGQCMFRlx9Bq0MuSh5pDhDTqRq/MnxxD\nW7qZg15AXoNnLrR60vV9gHjzkp1UkcU9viRIuAIwU0BjwDncp9z1seqKh+/eJV3f\nxstQe2rzUEptWLIiPFoOBWZuw9wJ/Hunjik3a9T/\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIByjCCAVCgAwIBAgIBATAKBggqhkjOPQQDAzAuMQswCQYDVQQGEwJFVTENMAsG\nA1UEChMEVGVzdDEQMA4GA1UEAxMHVGVzdCBDQTAeFw0yMjA4MTUwOTE3MTFaFw0y\nMjA4MTYwOTE3MTFaMC4xCzAJBgNVBAYTAkVVMQ0wCwYDVQQKEwRUZXN0MRAwDgYD\nVQQDEwdUZXN0IENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEf96tstMNdNoNfYjl\nbGY6BvBFTsl9E3hpPnta7SJn6BqIYz6KEohDJ+8DXwUMVb5Ytr/QkEikg966HCY3\nA9TFBUdAs01TV8f2KoAPRQVrh+ccSLLJyACENfZ5VbGSQ0wso0IwQDAOBgNVHQ8B\nAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUs7vtuA+BkwrPXUMF\nUNRe+00Z4GcwCgYIKoZIzj0EAwMDaAAwZQIxAMPgE/Z+1Dcj+lH7jioE16Hig0HQ\nFC4qBx1UU05H05Gs23ECB1hzD2qXikVpaNyuDgIwbogEu42wIwpDa5xdJIZcIhmz\nDIuPvEscUDjU3C+1GPxmACcRMPv9QVUEcBAvZkfn\n-----END CERTIFICATE-----\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThen you can configure heimdall to use it like follows:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/opt/heimdall/keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_subject\"\u003eSubject\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis configuration type enables extraction of subject information from responses received by Heimdall from authentication services. Following properties are available.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eid\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the id of the subject in the JSON object.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003eattributes\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eA \u003ca href=\"https://github.com/tidwall/gjson/blob/master/SYNTAX.md\"\u003eGJSON Path\u003c/a\u003e pointing to the attributes of the subject in the JSON object. Defaults to \u003ccode\u003e@this\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 26. Extracting subject id from an \u003ca href=\"https://tools.ietf.org/html/rfc7662\"\u003eOAuth2 Introspection\u003c/a\u003e endpoint response.\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example shows how to extract the subject id from an \u003ca href=\"https://tools.ietf.org/html/rfc7662\"\u003eOAuth2 Introspection\u003c/a\u003e endpoint response and set the subject attributes to the entire response\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esub\u003c/span\u003e\n\u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"err\"\u003e@\u003c/span\u003e\u003cspan class=\"s\"\u003ethis\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eSetting \u003ccode\u003eattributes\u003c/code\u003e was actually not required, as \u003ccode\u003e@this\u003c/code\u003e would be set by default anyway.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 27. Extracting subject id from an \u003ca href=\"https://www.ory.sh/docs/kratos/\"\u003eOry Kratos\u003c/a\u003e \u0026#34;whoami\u0026#34; endpoint response\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThis example shows how to extract the subject id from an \u003ca href=\"https://www.ory.sh/docs/kratos/\"\u003eOry Kratos\u003c/a\u003e \u0026#34;whoami\u0026#34; endpoint response and set the subject attributes to the entire response. \u003ccode\u003eattributes\u003c/code\u003e is not configured, so default is used.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eidentity.id\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_tls\"\u003eTLS\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eFollowing are the supported TLS configuration properties:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ekey_store\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003e\u003ca href=\"#_key_store\"\u003eKey Store\u003c/a\u003e\u003c/em\u003e (mandatory)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe key store containing the cryptographic material. At least one private key and the corresponding certificate must be present.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ekey_id\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eIf the \u003ccode\u003ekey_store\u003c/code\u003e contains multiple keys, this property can be used to specify the key to use (see also \u003ca href=\"#_key_id_lookup\"\u003eKey-Id Lookup\u003c/a\u003e). If not specified, the first key is used. If specified, but there is no key for the given key id present, an error is raised and heimdall will refuse to start.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003emin_version\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eThe minimal TLS version to support. Can be either \u003ccode\u003eTLS1.2\u003c/code\u003e or \u003ccode\u003eTLS1.3\u003c/code\u003e. Defaults to \u003ccode\u003eTLS1.3\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003ecipher_suites\u003c/code\u003e\u003c/strong\u003e: \u003cem\u003estring array\u003c/em\u003e (optional)\u003c/p\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eCan be configured if \u003ccode\u003emin_version\u003c/code\u003e is set to \u003ccode\u003eTLS1.2\u003c/code\u003e. If \u003ccode\u003emin_version\u003c/code\u003e is set to \u003ccode\u003eTLS1.3\u003c/code\u003e the configured values are ignored. Only the following PFS cipher suites are supported:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eTLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eDefaults to the last six cipher suites if \u003ccode\u003emin_version\u003c/code\u003e is set to \u003ccode\u003eTLS1.2\u003c/code\u003e and \u003ccode\u003ecipher_suites\u003c/code\u003e is not configured.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"exampleblock\"\u003e\n\u003cdiv class=\"title\"\u003eExample 28. Example configuration\u003c/div\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVeryInsecure!\u003c/span\u003e\n\u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\n\u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\n\u003cspan class=\"na\"\u003ecipher_suites\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"sect1\"\u003e\n\u003ch2 id=\"_key_id_lookup\"\u003eKey-Id Lookup\u003c/h2\u003e\n\u003cdiv class=\"sectionbody\"\u003e\n\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eWhen heimdall loads a key store, following algorithm is used to get the key id for the key:\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"ulist\"\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eif the PEM entry with the private key has \u003ccode\u003eX-Key-ID\u003c/code\u003e header specified, this value is used as key id\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOtherwise, if an X.509 certificate is present for the private key, and it has the \u003ccode\u003eSubject Key Identifier\u003c/code\u003e extension set, the hex representation of it is used as key id.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eOtherwise, heimdall calculates the value for the \u003ccode\u003eSubject Key Identifier\u003c/code\u003e according to \u003ca href=\"https://www.ietf.org/rfc/rfc3280.html#section-4.2.1.2\"\u003eRFC 3280, Section 4.2.1.2\u003c/a\u003e and uses hex representation of it as key id.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Configuration Reference"],"tags":null,"title":"Type Definitions","url":"/docs/configuration/types/"},{"categories":null,"content":" Below you can find possible contents (not exhaustive) for Heimdall’s config.yaml file. Head over to configuration documentation to get detailed explanation.\nserve: host: 127.0.0.1 port: 4469 respond: verbose: true with: authorization_error: code: 404 authentication_error: code: 404 timeout: read: 2s write: 5s idle: 2m connections_limit: max_per_host: 10 max_idle: 100 max_idle_per_host: 50 buffer_limit: read: 10KB write: 10KB cors: allowed_origins: - example.org allowed_methods: - GET - POST allowed_headers: - Authorization exposed_headers: - X-My-Header allow_credentials: true max_age: 1m tls: key_store: path: /path/to/key/store.pem password: VerySecure! key_id: first_entry min_version: TLS1.2 cipher_suites: - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 trusted_proxies: - 192.168.1.0/24 management: host: 127.0.0.1 port: 4457 timeout: read: 2s write: 5s idle: 2m cors: allowed_origins: - example.org allowed_methods: - GET - POST allowed_headers: - Authorization exposed_headers: - X-My-Header allow_credentials: true max_age: 1m tls: key_store: path: /path/to/key/store.pem min_version: TLS1.2 cache: type: redis-sentinel config: db: 2 master: whatever nodes: - foo:1234 - bar:1234 credentials: path: /path/to/credentials.yaml tls: key_store: path: /path/to/redis_client_keystore.pem key_id: bf5d129a7fec8b1fde11eab459784cc2f14e6c1d min_version: TLS1.2 cipher_suites: - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 client_cache: ttl: 10m max_flush_delay: 20us secrets_reload_enabled: true log: level: debug format: text tracing: enabled: true span_processor: batch metrics: enabled: true profiling: enabled: false host: 0.0.0.0 port: 9000 mechanisms: authenticators: - id: anonymous_authenticator type: anonymous - id: unauthorized_authenticator type: unauthorized - id: foo type: basic_auth config: user_id: bar password: baz allow_fallback_on_error: true - id: kratos_session_authenticator type: generic config: identity_info_endpoint: url: https://127.0.0.1:4433/sessions/whoami auth: auth: type: basic_auth config: user: foo password: bar retry: max_delay: 300ms give_up_after: 2s authentication_data_source: - cookie: ory_kratos_session forward_cookies: - ory_kratos_session subject: attributes: \u0026#34;@this\u0026#34; id: \u0026#34;identity.id\u0026#34; allow_fallback_on_error: true - id: hydra_authenticator type: oauth2_introspection config: introspection_endpoint: url: https://hydra:4445/oauth2/introspect retry: max_delay: 300ms give_up_after: 2s auth: type: api_key config: in: header name: X-Api-Key value: VerySecret! token_source: - header: Authorization scheme: Bearer - query_parameter: access_token - body_parameter: access_token assertions: issuers: - https://127.0.0.1:4444/ scopes: - foo - bar audience: - bla subject: attributes: \u0026#34;@this\u0026#34; id: \u0026#34;sub\u0026#34; allow_fallback_on_error: true - id: jwt_authenticator type: jwt config: metadata_endpoint: url: https://auth-server/.well-known/oauth-authorization-server disable_issuer_identifier_verification: true http_cache: enabled: true cache_ttl: 1h jwt_source: - header: Authorization scheme: Bearer - query_parameter: access_token - body_parameter: access_token assertions: audience: - bla scopes: - foo allowed_algorithms: - RS256 subject: attributes: \u0026#34;@this\u0026#34; id: \u0026#34;identity.id\u0026#34; cache_ttl: 5m allow_fallback_on_error: true authorizers: - id: allow_all_authorizer type: allow - id: deny_all_authorizer type: deny - id: remote_authorizer type: remote config: endpoint: url: https://my-authz-system/{{ .Values.some-key }} method: POST headers: foo-bar: \u0026#34;{{ .Subject.ID }}\u0026#34; auth: type: api_key config: in: header name: X-API-Key value: super duper secret values: some-key: some-value payload: \u0026#34;https://bla.bar\u0026#34; expressions: - expression: | Payload.response == true forward_response_headers_to_upstream: - bla-bar - id: user_is_admin_authz type: cel config: expressions: - expression: \u0026#34;\u0026#39;admin\u0026#39; in Subject.Attributes.groups\u0026#34; contextualizers: - id: subscription_contextualizer type: generic config: endpoint: url: https://foo.bar method: GET headers: bla: bla auth: type: oauth2_client_credentials config: auth_method: request_body token_url: https://bar.foo client_id: foo client_secret: bar cache_ttl: 20s header: name: X-Foo scheme: Bar payload: foo - id: profile_data_contextualizer type: generic config: endpoint: url: https://profile headers: foo: bar continue_pipeline_on_error: true finalizers: - id: jwt type: jwt config: signer: name: foobar key_store: path: /opt/heimdall/keystore.pem password: VeryInsecure! key_id: foo ttl: 5m header: name: Foo scheme: Bar claims: \u0026#34;{\u0026#39;user\u0026#39;: {{ quote .Subject.ID }} }\u0026#34; - id: bla type: header config: headers: foo-bar: bla - id: blabla type: cookie config: cookies: foo-bar: \u0026#39;{{ .Subject.ID }}\u0026#39; - id: get_token type: oauth2_client_credentials config: header: name: X-Token token_url: https://my-oauth-provider.com/token client_id: my_client client_secret: VerySecret! auth_method: basic_auth cache_ttl: 5m scopes: - foo - bar error_handlers: - id: default type: default - id: authenticate_with_kratos type: redirect config: to: https://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }} default_rule: backtracking_enabled: false execute: - authenticator: anonymous_authenticator - finalizer: jwt on_error: - error_handler: authenticate_with_kratos if: | ((type(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;kratos_session_authenticator\u0026#34;) || type(Error) == authorization_error) \u0026amp;\u0026amp; Request.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;*/*\u0026#34;) providers: file_system: src: test_rules.yaml watch: true http_endpoint: watch_interval: 5m endpoints: - url: https://foo.bar/ruleset1 http_cache: enabled: false - url: https://foo.bar/ruleset2 retry: give_up_after: 5s max_delay: 250ms auth: type: api_key config: name: api_key value: super-secret in: cookie header: X-Customer-Header: Some Value cloud_blob: watch_interval: 1m buckets: - url: gs://my-bucket prefix: service1 - url: azblob://my-bucket prefix: service2 - url: s3://my-bucket/my-rule-set kubernetes: auth_class: foo tls: key_id: foo key_store: path: /path/to/pem.file password: VerySecret! min_version: TLS1.3 ","description":"","html_content":"\u003cdiv class=\"paragraph\"\u003e\n\u003cp\u003eBelow you can find possible contents (not exhaustive) for Heimdall’s \u003ccode\u003econfig.yaml\u003c/code\u003e file. Head over to configuration documentation to get detailed explanation.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"listingblock\"\u003e\n\u003cdiv class=\"content\"\u003e\n\u003cpre class=\"rouge highlight\"\u003e\u003ccode data-lang=\"yaml\"\u003e\u003cspan class=\"na\"\u003eserve\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4469\u003c/span\u003e\n \u003cspan class=\"na\"\u003erespond\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003everbose\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewith\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthorization_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e404\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e404\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2m\u003c/span\u003e\n \u003cspan class=\"na\"\u003econnections_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_per_host\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e10\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_idle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e100\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_idle_per_host\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e50\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuffer_limit\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10KB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10KB\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecors\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_origins\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eexample.org\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_methods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePOST\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexposed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eX-My-Header\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_credentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_age\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1m\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/key/store.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecure!\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efirst_entry\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecipher_suites\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\u003c/span\u003e\n \u003cspan class=\"na\"\u003etrusted_proxies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003e192.168.1.0/24\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emanagement\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e127.0.0.1\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e4457\u003c/span\u003e\n \u003cspan class=\"na\"\u003etimeout\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eread\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewrite\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidle\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2m\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecors\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_origins\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eexample.org\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_methods\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ePOST\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexposed_headers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eX-My-Header\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_credentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_age\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1m\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/key/store.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003ecache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredis-sentinel\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003edb\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e2\u003c/span\u003e\n \u003cspan class=\"na\"\u003emaster\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ewhatever\u003c/span\u003e\n \u003cspan class=\"na\"\u003enodes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo:1234\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar:1234\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecredentials\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/credentials.yaml\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/redis_client_keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebf5d129a7fec8b1fde11eab459784cc2f14e6c1d\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.2\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecipher_suites\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e10m\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_flush_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e20us\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003esecrets_reload_enabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003elog\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003elevel\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edebug\u003c/span\u003e\n \u003cspan class=\"na\"\u003eformat\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etext\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003etracing\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003espan_processor\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebatch\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emetrics\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eprofiling\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehost\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e0.0.0.0\u003c/span\u003e\n \u003cspan class=\"na\"\u003eport\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e9000\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003emechanisms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthenticators\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eunauthorized_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eunauthorized\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebaz\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_fallback_on_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ekratos_session_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eidentity_info_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4433/sessions/whoami\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003euser\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003eretry\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e300ms\u003c/span\u003e\n \u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauthentication_data_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ecookie\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eory_kratos_session\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_cookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eory_kratos_session\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@this\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eidentity.id\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_fallback_on_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehydra_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_introspection\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eintrospection_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://hydra:4445/oauth2/introspect\u003c/span\u003e\n \u003cspan class=\"na\"\u003eretry\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e300ms\u003c/span\u003e\n \u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e2s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Api-Key\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecret!\u003c/span\u003e\n \u003cspan class=\"na\"\u003etoken_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003equery_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ebody_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eissuers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4444/\u003c/span\u003e\n \u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaudience\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@this\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003esub\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_fallback_on_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt_authenticator\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003emetadata_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://auth-server/.well-known/oauth-authorization-server\u003c/span\u003e\n \u003cspan class=\"na\"\u003edisable_issuer_identifier_verification\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1h\u003c/span\u003e\n \u003cspan class=\"na\"\u003ejwt_source\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eAuthorization\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBearer\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003equery_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003ebody_parameter\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eaccess_token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eassertions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eaudience\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\n \u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallowed_algorithms\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003eRS256\u003c/span\u003e\n \u003cspan class=\"na\"\u003esubject\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eattributes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e@this\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003eidentity.id\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eallow_fallback_on_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eauthorizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow_all_authorizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eallow\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny_all_authorizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edeny\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote_authorizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eremote\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://my-authz-system/{{ .Values.some-key }}\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ePOST\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efoo-bar\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-API-Key\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esuper duper secret\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalues\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esome-key\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esome-value\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003ehttps://bla.bar\u0026#34;\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003ePayload.response == true\u003c/span\u003e\n \u003cspan class=\"na\"\u003eforward_response_headers_to_upstream\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebla-bar\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003euser_is_admin_authz\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecel\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexpressions\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eexpression\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#39;admin\u0026#39;\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003ein\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003eSubject.Attributes.groups\u0026#34;\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003econtextualizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esubscription_contextualizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar\u003c/span\u003e\n \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eGET\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebla\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_client_credentials\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_method\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003erequest_body\u003c/span\u003e\n \u003cspan class=\"na\"\u003etoken_url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://bar.foo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_secret\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e20s\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Foo\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBar\u003c/span\u003e\n \u003cspan class=\"na\"\u003epayload\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eprofile_data_contextualizer\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egeneric\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://profile\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efoo\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n \u003cspan class=\"na\"\u003econtinue_pipeline_on_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003efinalizers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esigner\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoobar\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/opt/heimdall/keystore.pem\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVeryInsecure!\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003ettl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eFoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003escheme\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eBar\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclaims\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"s\"\u003e{\u0026#39;user\u0026#39;:\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003equote\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}\u0026#34;\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eheader\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efoo-bar\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebla\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eblabla\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecookie\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecookies\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efoo-bar\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"s\"\u003e{{\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e.Subject.ID\u003c/span\u003e\u003cspan class=\"nv\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e}}\u0026#39;\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eget_token\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eoauth2_client_credentials\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eX-Token\u003c/span\u003e\n \u003cspan class=\"na\"\u003etoken_url\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://my-oauth-provider.com/token\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003emy_client\u003c/span\u003e\n \u003cspan class=\"na\"\u003eclient_secret\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecret!\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_method\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ebasic_auth\u003c/span\u003e\n \u003cspan class=\"na\"\u003ecache_ttl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003escopes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"s\"\u003ebar\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003eerror_handlers\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003edefault\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticate_with_kratos\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eredirect\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eto\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }}\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003edefault_rule\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebacktracking_enabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"na\"\u003eexecute\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eauthenticator\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eanonymous_authenticator\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003efinalizer\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ejwt\u003c/span\u003e\n \u003cspan class=\"na\"\u003eon_error\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eerror_handler\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eauthenticate_with_kratos\u003c/span\u003e\n \u003cspan class=\"na\"\u003eif\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"pi\"\u003e|\u003c/span\u003e\n \u003cspan class=\"s\"\u003e((type(Error) == authentication_error \u0026amp;\u0026amp; Error.Source == \u0026#34;kratos_session_authenticator\u0026#34;) ||\u003c/span\u003e\n \u003cspan class=\"s\"\u003etype(Error) == authorization_error) \u0026amp;\u0026amp;\u003c/span\u003e\n \u003cspan class=\"s\"\u003eRequest.Header(\u0026#34;Accept\u0026#34;).contains(\u0026#34;*/*\u0026#34;)\u003c/span\u003e\n\n\u003cspan class=\"na\"\u003eproviders\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003efile_system\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003esrc\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003etest_rules.yaml\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003ehttp_endpoint\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch_interval\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5m\u003c/span\u003e\n \u003cspan class=\"na\"\u003eendpoints\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar/ruleset1\u003c/span\u003e\n \u003cspan class=\"na\"\u003ehttp_cache\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eenabled\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ehttps://foo.bar/ruleset2\u003c/span\u003e\n \u003cspan class=\"na\"\u003eretry\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003egive_up_after\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e5s\u003c/span\u003e\n \u003cspan class=\"na\"\u003emax_delay\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e250ms\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003econfig\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eapi_key\u003c/span\u003e\n \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003esuper-secret\u003c/span\u003e\n \u003cspan class=\"na\"\u003ein\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003ecookie\u003c/span\u003e\n \u003cspan class=\"na\"\u003eheader\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eX-Customer-Header\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eSome Value\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003ecloud_blob\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ewatch_interval\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e1m\u003c/span\u003e\n \u003cspan class=\"na\"\u003ebuckets\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003egs://my-bucket\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservice1\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eazblob://my-bucket\u003c/span\u003e\n \u003cspan class=\"na\"\u003eprefix\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eservice2\u003c/span\u003e\n \u003cspan class=\"pi\"\u003e-\u003c/span\u003e \u003cspan class=\"na\"\u003eurl\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003es3://my-bucket/my-rule-set\u003c/span\u003e\n\n \u003cspan class=\"na\"\u003ekubernetes\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003eauth_class\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003etls\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_id\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003efoo\u003c/span\u003e\n \u003cspan class=\"na\"\u003ekey_store\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e\n \u003cspan class=\"na\"\u003epath\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003e/path/to/pem.file\u003c/span\u003e\n \u003cspan class=\"na\"\u003epassword\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eVerySecret!\u003c/span\u003e\n \u003cspan class=\"na\"\u003emin_version\u003c/span\u003e\u003cspan class=\"pi\"\u003e:\u003c/span\u003e \u003cspan class=\"s\"\u003eTLS1.3\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n","sections":["Configuration Reference"],"tags":null,"title":"Reference","url":"/docs/configuration/reference/"}] \ No newline at end of file diff --git a/dev/index.xml b/dev/index.xml index b4fab25f8..d377e3a49 100644 --- a/dev/index.xml +++ b/dev/index.xml @@ -1,4 +1,4 @@ -Heimdall - a cloud native Identity Aware Proxy and Access Control Decision service on Heimdallhttps://dadrus.github.io/Recent content in Heimdall - a cloud native Identity Aware Proxy and Access Control Decision service on HeimdallHugoen-usMon, 17 Feb 2025 11:36:59 +0000Discover heimdallhttps://dadrus.github.io/docs/getting_started/discover_heimdall/Wed, 29 Nov 2023 22:03:28 +0200https://dadrus.github.io/docs/getting_started/discover_heimdall/<div class="sect1"> +Heimdall - a cloud native Identity Aware Proxy and Access Control Decision service on Heimdallhttps://dadrus.github.io/Recent content in Heimdall - a cloud native Identity Aware Proxy and Access Control Decision service on HeimdallHugoen-usTue, 18 Feb 2025 15:31:53 +0000Discover heimdallhttps://dadrus.github.io/docs/getting_started/discover_heimdall/Wed, 29 Nov 2023 22:03:28 +0200https://dadrus.github.io/docs/getting_started/discover_heimdall/<div class="sect1"> <h2 id="_what_is_heimdall">What is heimdall?</h2> <div class="sectionbody"> <div class="paragraph"> diff --git a/dev/sitemap.xml b/dev/sitemap.xml index 502a68ff0..b706105be 100644 --- a/dev/sitemap.xml +++ b/dev/sitemap.xml @@ -1 +1 @@ -https://dadrus.github.io/docs/getting_started/discover_heimdall/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/getting_started/installation/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/getting_started/protect_an_app/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/getting_started/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/proxies/caddy/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/concepts/pipelines/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/proxies/contour/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/concepts/mechanisms/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/proxies/emissary/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/concepts/rules/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/proxies/envoy/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/concepts/provider/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/proxies/envoy_gateway/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/concepts/operating_modes/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/proxies/haproxy/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/proxies/istio/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/proxies/nginx/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/proxies/traefik/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/authz/opa/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/authz/openfga/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/authn/oidc_first_party_auth/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/operations/configuration/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/operations/cli/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/operations/observability/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/operations/cache/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/operations/security/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/services/main/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/services/management/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/mechanisms/catalogue/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/mechanisms/evaluation_objects/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/mechanisms/authenticators/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/mechanisms/authorizers/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/mechanisms/contextualizers/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/mechanisms/finalizers/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/mechanisms/error_handlers/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/rules/regular_rule/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/rules/default_rule/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/rules/rule_sets/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/rules/providers/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/configuration/types/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/configuration/reference/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/2025-02-17T11:36:59+00:00https://dadrus.github.io/openapi/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/authn/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/proxies/2025-02-17T11:36:59+00:00https://dadrus.github.io/guides/authz/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/rules/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/mechanisms/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/services/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/operations/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/concepts/2025-02-17T11:36:59+00:00https://dadrus.github.io/docs/configuration/2025-02-17T11:36:59+00:00https://dadrus.github.io/2025-02-17T11:36:59+00:00https://dadrus.github.io/categories/https://dadrus.github.io/tags/ \ No newline at end of file +https://dadrus.github.io/docs/getting_started/discover_heimdall/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/getting_started/installation/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/getting_started/protect_an_app/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/getting_started/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/proxies/caddy/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/concepts/pipelines/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/proxies/contour/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/concepts/mechanisms/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/proxies/emissary/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/concepts/rules/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/proxies/envoy/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/concepts/provider/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/proxies/envoy_gateway/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/concepts/operating_modes/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/proxies/haproxy/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/proxies/istio/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/proxies/nginx/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/proxies/traefik/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/authz/opa/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/authz/openfga/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/authn/oidc_first_party_auth/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/operations/configuration/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/operations/cli/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/operations/observability/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/operations/cache/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/operations/security/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/services/main/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/services/management/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/mechanisms/catalogue/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/mechanisms/evaluation_objects/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/mechanisms/authenticators/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/mechanisms/authorizers/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/mechanisms/contextualizers/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/mechanisms/finalizers/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/mechanisms/error_handlers/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/rules/regular_rule/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/rules/default_rule/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/rules/rule_sets/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/rules/providers/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/configuration/types/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/configuration/reference/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/2025-02-18T15:31:53+00:00https://dadrus.github.io/openapi/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/authn/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/proxies/2025-02-18T15:31:53+00:00https://dadrus.github.io/guides/authz/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/rules/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/mechanisms/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/services/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/operations/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/concepts/2025-02-18T15:31:53+00:00https://dadrus.github.io/docs/configuration/2025-02-18T15:31:53+00:00https://dadrus.github.io/2025-02-18T15:31:53+00:00https://dadrus.github.io/categories/https://dadrus.github.io/tags/ \ No newline at end of file