Use JWT authorization with service intentions

JSON Web Tokens (JWT) are a method for identity-based access to services for both humans and machines. The JWT provider configuration entry enables you to define JWTs as part of a JSON Web Key Set (JWKS), which contains the information necessary for Consul to validate access and configure behavior for requests that include JWTs.

By specifying a JSON Web Key Set (JWKS) in the configuration entry and referencing the key set in a service intention, Consul can enforce service intentions based on the presence of a JWT. This security configuration is not related to the JSON Web Token Auth Method, which associates JWTs with the Consul ACLs instead of service intentions.

Workflow

The process to configure your network to enforce service intentions based on JSON web tokens consists of the following steps:

  1. Create a JWT provider configuration entry. This configuration entry defines rules and behaviors for verifying tokens. These configurations apply to admin partitions in Consul Enterprise, which is functionally equivalent to a datacenter in Consul OSS. Then, write the jwt-provider configuration entry to Consul. The ACL policy requirement to read and modify this configuration entry is mesh:write.

  2. Create or update a service intentions configuration entry to reference the JWT provider. This configuration invokes the name of the jwt-provider configuration entry you created, which causes the Envoy proxy to verify the token and the permissions it authorizes before the incoming request is accepted. Then, write the service-intentions configuration entry that references the JWT to Consul. The ACL policy requirement to read and modify this configuration entry is mesh:write.

Wildcards and intention defaults

Because intentions without tokens are authorized when they arrive at the destination proxy, a common pattern for the service-intentions configuration entry sets the entry’s Name field as a wildcard, *. This pattern enables you to apply incoming requests from specific services to every service in the datacenter.

When configuring your deployment to enforce service intentions with JSON Web Tokens, it is possible for multiple tokens with different permissions to apply to a single service’s incoming request based on attributes such as HTTP path or the request method. Because the service-intentions configuration entry applies the intention that most closely matches the request, using the Name wildcard with specific JWT authorization configurations can lead to unintended results.

When you set the JWT{}.Providers field in a service intentions configuration entry to the wildcard *, you can configure default behavior for all services that present a token that matches an existing JWT provider configuration entry. In this configuration, services that have a valid token but do not have a more specific matching intention default to the behavior defined in the wildcard intention.

Usage

To configure Envoy proxies in the service mesh to validate JWTs before forwarding requests to servers, complete the following steps:

Create a JWT provider configuration entry

The jwt-provider configuration requires the following fields:

  • Kind: This field must be set to "jwt-provider"
  • Name: We recommend naming the configuration file after the JWT provider used in the configuration.
  • Issuer: This field must match the token’s iss claim

You must also specify a JSON Web Key Set in the JSONWebKeySet field. You can specify the JWKS as one of the following:

  • A local string
  • A path to a local file
  • A remote location specified with a URI

A JWKS can be made available locally or remotely, but not both. In addition, a local JWKS must be specified as either a string or a path to the file containing the token.

You can also specify where the JWT is located, a retry policy, and text to append to the header when forwarding the request after token validation.

The following example configures Consul to fetch a JSON Web Token issued by Okta. Consul fetches the token from the URI and keeps it in its cache for 30 minutes before the token expires. After validation, the token is forwarded to the backend with user-token appended to the HTTP header.

  1. Kind = "jwt-provider"
  2. Name = "okta"
  3. Issuer = "okta"
  4. JSONWebKeySet = {
  5. Remote = {
  6. URI = "https://<org>.okta.com/oauth2/default/v1/keys"
  7. CacheDuration = "30m"
  8. }
  9. }
  10. Forwarding = {
  11. HeaderName = "user-token"
  12. }

Refer to JWT provider configuration entry for more information about the fields you can configure.

To write the configuration entry to Consul, use the consul config write command:

  1. $ consul config write okta-provider.hcl

Update service intentions

After you create the JWT provider entry, you can update your service intentions so that proxies validate the token before authorizing a request. The following example includes the minimum required configuration to enable JWT authorization with service intentions:

  1. Kind = "service-intentions"
  2. Name = "web"
  3. JWT = {
  4. Providers = [
  5. {
  6. Name = "okta"
  7. }
  8. ]
  9. }

You can include additional configuration information to require the token to match specific claims. You can also configure the JWT field to apply only to requests that come from certain HTTP paths. Refer to JWT validations with intentions for an example configuration.

After you update the service intention, write the configuration to Consul so that it takes effect:

  1. $ consul config write web-intention.hcl