The upcoming version of Eclipse Ditto 2.0.0 will be enhanced with the ability to alter policies based on policy actions.

Policy actions

This new concept of Policy actions allows upfront defined modifications to policies without the need for the one invoking the action to have “WRITE” permissions granted on the policy.

Token based activation of subject

Together with the concept of actions, a first action named activateTokenIntegration is added.
This action

When all the conditions were met for a policy entry, the action will inject a new subject into the matched policy entry which by default (the pattern is configurable) is the following. This syntax uses placeholders in order to extract information from the authenticated JWT and the policy entry:


integration:{{policy-entry:label}}:{{jwt:aud}}

The value of the injected subject will contain the expiry timestamp copied from the JWT "exp" (the expiration time of the token) claim.

Example use case

Assuming that you have configured a custom OpenID Connect provider some-openid-connect-provider as documented in the installation/operation guide:

ditto.gateway.authentication {
  oauth {
    openid-connect-issuers = {
      some-openid-connect-provider = "https://some-openid-connect-provider.com"
    }
  }
}

Let’s describe our scenario:

  • It is required to enable that a Ditto connection (e.g. an HTTP connection invoking an HTTP webhook) shall receive events whenever the temperature of a twin is modified
  • For security reasons however, the webhook shall not receive events longer than the expiration time of the JWT which was used in order to activate the webhook
  • The webhook can be extended by invoking the action again before the “expiry” time was reached

The underlying policy shall be the following one:

{
  "policyId": "my.namespace:policy-a",
  "entries": {
    "owner": {
      "subjects": {
        "some-openid-connect-provider:some-admin-id": {
          "type": "authenticated via OpenID connect provider <some-openid-connect-provider>"
        }
      },
      "resources": {
        "thing:/": {
          "grant": ["READ", "WRITE"],
          "revoke": []
        },
        "policy:/": {
          "grant": ["READ", "WRITE"],
          "revoke": []
        }
      }
    },
    "temperature-observer": {
      "subjects": {
        "some-openid-connect-provider:some-user-id": {
          "type": "authenticated via OpenID connect provider <some-openid-connect-provider>"
        }
      },
      "resources": {
        "thing:/features/temperature": {
          "grant": ["READ"],
          "revoke": []
        },
        "policy:/entries/temperature-observer/actions/activateTokenIntegration": {
          "grant": ["EXECUTE"],
          "revoke": []
        }
      }
    }
  }
}

The policy entry "temperature-observer" above describes that:

  • the user “some-user-id” may READ the "temperature" feature of things using this policy
  • is allowed to EXECUTE the activateTokenIntegration action in order to inject a subject derived from his provided JWT

Let’s assume that the authenticated JWT used for executing the action contained the following claims:

{
  "iss": "https://some-openid-connect-provider.com",
  "sub": "some-user-id",
  "exp": 1622802633,
  "aud": "some-specific-audience-0815"
}

The “exp” field contains the token expiry timestamp (seconds since epoch) and resolves to: Friday, June 4, 2021 10:30:33 AM.

Once the HTTP API POST /api/2/policies/{policyId}/entries/{label}/actions/activateTokenIntegration, with policyId=my.namespace:policy-a and label=temperature-observer,
is invoked (without any payload), a new subject will be injected when the described prerequisites were enforced successfully.

As a simplification, all possible policy entries may be injected with the subject by invoking the top level action
POST /api/2/policies/{policyId}/actions/activateTokenIntegration, with policyId=my.namespace:policy-a.

The value of the injected subject will contain the expiration timestamp from the JWT, so the injected policy subject integration:temperature-observer:some-specific-audience-0815 will result in a modified policy:

{
  "policyId": "my.namespace:policy-a",
  "entries": {
    "owner": { // unchanged ... },
    "temperature-observer": {
      "subjects": {
        "some-openid-connect-provider:some-user-id": {
          "type": "authenticated via OpenID connect provider <some-openid-connect-provider>"
        },
        "integration:temperature-observer:some-specific-audience-0815": {
          "type": "added via action <activateTokenIntegration>",
          "expiry": "2021-06-04T10:30:33Z"
        }
      },
      "resources": {
        "thing:/features/temperature": {
          "grant": ["READ"],
          "revoke": []
        },
        "policy:/entries/temperature-observer/actions/activateTokenIntegration": {
          "grant": ["EXECUTE"],
          "revoke": []
        }
      }
    }
  }
}

When we now have a managed HTTP connection which configures the authorizationContext to include the subject integration:temperature-observer:some-specific-audience-0815 for a connection target, this connection is allowed to publish changes to the temperature of all things using the above policy until the "expiry" timestamp was reached.
Afterwards, publishing changes automatically stops, unless the action is invoked again with a JWT having a longer “exp” time prolonging the injected policy subject.

Feedback?

Please get in touch if you have feedback or questions towards this new token based subject activation for policies.
Or do you have other use cases in mind you might be able to solve with this feature? Please let us know.



Ditto


The Eclipse Ditto team