Configuring identity-aware routing
Page last updated:
Identity-aware routing lets you route app-to-app traffic through the Gorouter over mutual TLS (mTLS), where the Gorouter validates the caller’s verified Cloud Foundry identity and enforces route policies before forwarding the request to your app. For an overview of how identity-aware routing works, see Identity-aware routing.
On this page you:
- Create an identity-aware domain, or use one your operator created.
- Map a route on that domain to a destination app.
- Add route policies that allow specific callers to reach the route. Identity-aware routes are default-deny: until a policy allows a caller, the Gorouter rejects it.
- Make app-to-app requests and consume the caller’s identity from the client-certificate header in the backend app.
Identity-aware routing requires an operator to have enabled an identity-aware (mTLS) domain in the deployment. See Enabling identity-aware routing.
Prerequisites
Before you configure identity-aware routing, ensure that:
You are using a version of the cf CLI that includes the route-policy commands (cf CLI v8 or later). To check your version, run:
$ cf version
For more information about updating the cf CLI, see Installing the cf CLI.
An operator has enabled an identity-aware (mTLS) domain in the deployment. See Enabling identity-aware routing.
You have the Space Developer role in the route’s space. Route policies are destination-controlled: they are managed by a Space Developer in the route’s space. Creating the domain itself requires admin (shared domain) or the OrgManager role (private domain), as described in the next section.
Create an identity-aware domain
Identity-aware routing is enabled on a domain when the domain is created, by adding the --enforce-route-policies flag. This setting is immutable: you cannot turn enforcement on or off for an existing domain.
An admin creates a shared identity-aware domain:
$ cf create-shared-domain apps.identity --enforce-route-policies
An OrgManager creates a private identity-aware domain:
$ cf create-private-domain my-org apps.identity --enforce-route-policies
You can optionally restrict which callers can be named as a policy source with --scope. The --scope flag is only valid together with --enforce-route-policies:
$ cf create-shared-domain apps.identity --enforce-route-policies --scope space
| Scope | Meaning |
|---|---|
any |
Policy sources can be in any org or space. |
org |
Policy sources must be in the same org as the route. |
space |
Policy sources must be in the same space as the route. |
After a route is created on an identity-aware domain, all callers are denied until a route policy allows them. The next sections cover mapping a route and adding policies.
For more about shared and private domains, see Configuring routes and domains.
Map a route on the identity-aware domain
Map a route on the identity-aware domain to your destination app — the app that receives identity-checked traffic — using the standard cf map-route command:
$ cf map-route backend apps.identity --hostname backend
This gives the backend app the route backend.apps.identity.
Nothing about the mapping command is special: the route is identity-aware because the domain enforces route policies. Until you add a policy (next section), the Gorouter denies all callers to this route. You can also declare the route in the app manifest’s routes: block, the same as any other route.
Add a route policy
Route policies are destination-controlled: a Space Developer in the route’s space adds them to allow named callers to reach the route. Without a matching policy, callers are denied by default.
Add a policy with cf add-route-policy:
$ cf add-route-policy DOMAIN --hostname HOSTNAME [SOURCE] [--path PATH]
Identify the caller with one of the following mutually exclusive source selectors:
| Flag | Allows callers that are… |
|---|---|
--source-app APP |
A specific app. Optionally narrow an ambiguous app name with --source-space and --source-org. |
--source-space SPACE |
Any app in a space. Optionally add --source-org. |
--source-org ORG |
Any app in an org. |
--source-any |
Any authenticated Cloud Foundry caller, subject to the domain’s --scope. |
--source SOURCE |
The raw source form: cf:app:<app-guid>, cf:space:<space-guid>, cf:org:<org-guid>, or cf:any. |
For example, to allow frontend-app to reach backend.apps.identity:
$ cf add-route-policy apps.identity --hostname backend --source-app frontend-app
You can express the same caller with the raw --source form, for example to allow every app in an org:
$ cf add-route-policy apps.identity --hostname backend --source cf:org:<org-guid>
If the route was created with a path, add --path to scope the policy to that path.
List route policies
List policies with cf route-policies, optionally filtered:
$ cf route-policies --domain apps.identity
Filter the output with:
--domain— filter by domain name.--hostname— filter by hostname.--path— filter by path.--labels— filter by a label selector, when policies are labeled for auditing.
The command lists each policy with its route and source. For example:
host domain path source scope name backend apps.identity cf:app:a1b2c3d4-1111-2222-3333-444455556666 app frontend-app
Remove a route policy
To remove a policy, run cf remove-route-policy with the same domain, hostname, and source you used to add it:
$ cf remove-route-policy apps.identity --hostname backend --source-app frontend-app
Add -f to skip the confirmation prompt. Removing the last policy that allowed a caller returns that caller to denied-by-default.
Make an app-to-app request
From the source app, make an HTTPS request to the destination’s identity-aware route, presenting the app’s Diego instance identity certificate as the client certificate. The platform mounts the certificate and private key in every app container at the paths given by the CF_INSTANCE_CERT and CF_INSTANCE_KEY environment variables.
The following illustrative curl call uses those credentials to reach backend.apps.identity:
$ curl --cert "$CF_INSTANCE_CERT" --key "$CF_INSTANCE_KEY" https://backend.apps.identity/
The Gorouter validates the certificate against the domain’s CA, checks the route’s policies, and forwards the request to the backend on success. If no policy allows the caller, the Gorouter returns an HTTP 403 Forbidden response (default-deny).
This is the same Diego instance identity issued to every app instance. The caller needs no extra credentials to make an identity-aware request.
Consume the client certificate in your app
When the Gorouter forwards an identity-aware request, it passes the caller’s verified certificate to the backend app in the X-Forwarded-Client-Cert (XFCC) header. The backend reads this header to learn the caller’s identity. The operator chooses the header format per domain with xfcc_format:
| Format | Header contents | Approximate size |
|---|---|---|
raw |
The full client certificate, base64-encoded PEM. | ~1.5 KB |
envoy |
A compact representation, Hash=<sha256>;Subject="<DN>". |
~300 B |
Your backend parses the certificate Subject organizational units to learn the caller’s app, space, and org: OU=app:<app-guid>, OU=space:<space-guid>, and OU=organization:<org-guid>. These are the same OUs described in The client certificate header and identity. For more about how Cloud Foundry forwards client certificates in general, see Forwarding client certificate to apps.
Consuming the envoy (hashed) XFCC value in Java apps relies on the java-buildpack-client-certificate-mapper (cloudfoundry/java-buildpack-client-certificate-mapper#11). If that support is not yet released in your buildpack, prefer the raw format for Java backends.
External client certificates
Not every caller is a Cloud Foundry app. Partner systems, IoT devices, and other external clients present their own certificates, which do not carry a Diego instance identity. For these callers, the operator configures an mTLS domain without --enforce-route-policies. The Gorouter validates the certificate against the domain’s CA and sets the XFCC header, and your app authorizes the request based on the header contents.
Do not add route policies for non-Cloud Foundry callers. Route policies key off the Cloud Foundry identity organizational units (app, space, org) that external certificates do not carry.
For more about this variant, see External client certificates.
Related reading
- Identity-aware routing
- Configuring routes and domains
- Configuring per-route options
- Enabling identity-aware routing
- RFC-0055: Identity-Aware Routing for Gorouter