diff --git a/custom-per-route-options.html.md.erb b/custom-per-route-options.html.md.erb index 56381ee8..095bdced 100644 --- a/custom-per-route-options.html.md.erb +++ b/custom-per-route-options.html.md.erb @@ -15,6 +15,10 @@ Gorouter supports the following per-route options, described in the sections bel - `hash_header`: Defines the HTTP header used for hash-based routing decisions. Required when `loadbalancing` is set to `hash`. Cannot be used with other load balancing algorithms. <%= vars.hash_routing_version %> - `hash_balance`: Sets the float number for the balance factor used by Gorouter to manage load imbalance applying the hash-based routing for this route. Optional when `loadbalancing` is `hash`. Cannot be used with other algorithms. <%= vars.hash_routing_version %> +
+Identity-aware routing is configured with the dedicated cf add-route-policy / cf route-policies / cf remove-route-policy commands rather than the --option flag described here. The Gorouter applies route policies through internal route options (route_policy_scope, route_policy_sources) that are managed by the platform and are not returned in route API responses. See Configuring identity-aware routing.
+
+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](../../cf-cli/install-go-cli.html). + +* An operator has enabled an identity-aware (mTLS) domain in the deployment. See [Enabling identity-aware routing](../../deploying/cf-deployment/enable-identity-aware-routing.html). + +* 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 may 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 may 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. | +
+$ 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 <%= vars.app_runtime_abbr %> 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. |
+
+$ 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 | +
+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.
+
+Do not add route policies for non-<%= vars.app_runtime_abbr %> callers. Route policies key off the <%= vars.app_runtime_abbr %> identity organizational units (app, space, org) that external certificates do not carry. +
+ +For more about this variant, see [External client certificates](../../concepts/identity-aware-routing.html#external-mtls). + + +## Related reading + +* [Identity-aware routing](../../concepts/identity-aware-routing.html) +* [Configuring routes and domains](routes-domains.html) +* [Configuring per-route options](../custom-per-route-options.html) +* [Enabling identity-aware routing](../../deploying/cf-deployment/enable-identity-aware-routing.html) +* [RFC-0055: Identity-Aware Routing for Gorouter](https://github.com/cloudfoundry/community/blob/main/toc/rfc/rfc-0055-identity-aware-routing-for-gorouter.md) diff --git a/deploy-apps/routes-domains.html.md.erb b/deploy-apps/routes-domains.html.md.erb index 563ae270..19373ba4 100644 --- a/deploy-apps/routes-domains.html.md.erb +++ b/deploy-apps/routes-domains.html.md.erb @@ -727,6 +727,10 @@ Admins can create an HTTP shared domain with the `cf create-shared-domain` comma $ cf create-shared-domain <%= vars.app_domain %> ``` +
+To create a domain that requires mutual TLS and enforces identity-based route policies, add the --enforce-route-policies flag (optionally with --scope). This setting is fixed when the domain is created and cannot be changed afterward. See Configuring identity-aware routing.
+
cf CLI v7+ does not support TCP routing or creating shared domains with router groups.
@@ -768,6 +772,10 @@ Org managers can create a private domain by running: $ cf create-private-domain example-org <%= vars.private_app_domain %> ``` +
+Org managers can create an identity-aware private domain by adding --enforce-route-policies (optionally with --scope). This setting is fixed at creation. See Configuring identity-aware routing.
+