Default Rule

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.

Configuration

The configuration of the default rule can be done by making use of the default_rule property and configuring the options shown below.

The default rule does not support all the properties, which can be configured in an regular rule.

  • It can not be used to forward requests to an upstream service, heimdall is protecting. So, if you operate heimdall in the reverse proxy mode, the default rule should be configured to reject requests. Otherwise, heimdall will respond with an error.

  • A default rule does also reject requests with encoded slashes in the path of the URL with 400 Bad Request, which can be configured on the level of a regular rule.

  • backtracking_enabled: boolean (optional)

    Enables or disables backtracking while matching the rules globally. Defaults to false.

  • execute: Authentication & Authorization Pipeline (mandatory)

    Which 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).

  • on_error: Error Pipeline (optional)

    Which 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.

Example 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 && Error.Source == "session_cookie_from_kratos_authn"

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.

Obviously, the authentication & 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:

id: 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?

Last updated on Sep 13, 2024