- Name: Domain-Scoped mTLS for GoRouter
- Start Date: 2026-02-16
- Author(s): @rkoster, @beyhan, @maxmoehl
- Status: Draft
- RFC Pull Request: community#1438
Enable per-domain mutual TLS (mTLS) on GoRouter with optional identity extraction and authorization enforcement. Operators configure domains that require client certificates, specify how to handle the XFCC header, and optionally enable platform-enforced access control.
This infrastructure supports multiple use cases: authenticated CF app-to-app communication via internal domains (e.g., apps.mtls.internal), external client certificate validation for partner integrations, and cross-CF federation between installations.
For CF app-to-app routing, this follows the same default-deny model as container-to-container network policies: all traffic is blocked unless explicitly allowed.
Cloud Foundry applications can communicate via external routes (through GoRouter) or container-to-container networking (direct). Neither provides per-domain mTLS requirements with platform-enforced authorization:
- External routes: Traffic leaves the VPC to reach the load balancer, adding latency and cost. GoRouter's client certificate settings are global—enabling strict mTLS for one domain affects all domains.
- C2C networking: Requires
network.writescope, which is not granted to space developers by default—operators must setenable_space_developer_self_service: true. Also lacks load balancing, observability, and identity forwarding.
This RFC addresses several use cases that require per-domain mTLS:
-
CF app-to-app routing: Applications need authenticated internal communication where only CF apps can connect (via instance identity), traffic stays internal, the platform enforces which apps can call which routes, and standard GoRouter features work (load balancing, retries, observability).
-
External client certificates: Some platforms need to validate client certificates from external systems (partner integrations, IoT devices) on specific domains without affecting other domains or requiring CF-specific identity handling.
-
Cross-CF federation: Applications on one CF installation need to securely communicate with applications on another CF installation, each with its own CA and GUID namespace.
The gap: GoRouter has no mechanism for requiring mTLS on specific domains while leaving others unaffected, and no way to enforce authorization rules at the route level based on caller identity.
For CF app-to-app routing specifically, authentication alone is insufficient. Without authorization enforcement, any authenticated app could access any route on the mTLS domain, defeating the purpose of platform-enforced security.
GoRouter gains the ability to require client certificates for specific domains, with configurable identity extraction and authorization enforcement. This is implemented in phases:
- Phase 1a (mTLS Domain Infrastructure): GoRouter requires and validates client certificates for configured domains. The XFCC header is set with certificate details. This alone enables external client certificate validation.
- Phase 1b (CF Identity & Authorization): Optional, opt-in behavior where GoRouter extracts CF identity from Diego instance certificates and enforces authorization rules. This enables CF app-to-app routing and cross-CF federation.
- Phase 2 (Egress HTTP Proxy): Opt-in enhancement where the sidecar proxy automatically injects instance identity certificates, simplifying client adoption for CF app-to-app routing. Users enable this per-app; it is not required for Phase 1 functionality.
The diagram below shows CF app-to-app routing (the most complex use case). For external client certificate validation, only GoRouter and the backend app are involved—external clients connect directly to GoRouter with their certificates.
flowchart LR
subgraph "App A Container"
AppA["App A"]
ProxyA["Envoy<br/>(egress proxy)"]
end
subgraph "GoRouter"
GR["1. Validate cert<br/>(Instance Identity CA)"]
Auth["2. Check authorization"]
end
subgraph "App B Container"
ProxyB["Envoy<br/>(validates GoRouter cert)"]
AppB["App B"]
end
AppA -->|"HTTP"| ProxyA
ProxyA -->|"mTLS<br/>(instance cert)"| GR
GR --> Auth
Auth -->|"authorized<br/>mTLS<br/>(GoRouter cert)"| ProxyB
Auth -.->|"403 Forbidden"| ProxyA
ProxyB -->|"HTTP + XFCC"| AppB
GoRouter gains the ability to require client certificates for specific domains while leaving other domains unaffected. This infrastructure is generic and can be used for multiple purposes beyond CF app-to-app routing.
How it works:
- Operator configures a domain with mTLS requirements in the
mtls_domainsconfiguration - Operator marks the domain as mTLS-enabled in Cloud Controller (
mtls_enabled: true) - DNS (BOSH DNS or external) resolves the domain to GoRouter instances
- Applications map routes to this domain like any shared domain
- When a client connects, GoRouter:
- Requires a client certificate
- Validates it against the configured CA
- Sets the XFCC header with certificate details (format configurable)
- Optionally extracts identity and enforces authorization (Phase 1b)
Configuration:
router:
mtls_domains:
# Domain pattern requiring mTLS. Wildcards supported.
- domain: "*.apps.mtls.internal"
# CA certificate(s) for validating client certs (PEM-encoded)
ca_certs: ((diego_instance_identity_ca.certificate))
# How to handle the X-Forwarded-Client-Cert header:
# sanitize_set (default, recommended) - Remove incoming XFCC, set from client cert
# forward - Pass through existing XFCC header
# always_forward - Always pass through, even if no client cert
forwarded_client_cert: sanitize_set
xfcc:
# Format of the XFCC header:
# raw (default) - Full base64-encoded certificate (~1.5KB)
# envoy - Compact format (~300 bytes):
# Hash=<sha256>;Subject="CN=<instance-id>,OU=app:<guid>..."
format: envoy
# How to extract caller identity from the certificate:
# none (default) - No extraction; backend parses XFCC itself
# cf_ou - Extract app/space/org GUIDs from Diego instance identity
# certificate OU fields (app:<guid>, space:<guid>, organization:<guid>)
identity_extractor: cf_ou
authorization:
# How to enforce access control:
# none (default) - Any valid certificate accepted
# cf_identity - Enforce rules using CF identity hierarchy
# (requires identity_extractor: cf_ou)
mode: cf_identity
# Operator-level caller restrictions (only for mode: cf_identity).
# Two approaches (mutually exclusive):
#
# 1. Relative boundary (scope) - compares caller identity against
# the route destination's tags (organization_id, space_id) which
# are set by the route-emitter for each app instance:
# any (default) - Any authenticated caller passes domain-level checks
# org - Caller must be in the same org as the route's destination app
# space - Caller must be in the same space as the route's destination app
#
# 2. Explicit boundary (orgs/spaces) - absolute list of allowed
# caller org/space GUIDs. Useful for cross-CF federation where
# scope checks are meaningless (remote GUIDs have no local context).
config:
# Option 1: Relative boundary (recommended for single-CF)
scope: org
# Option 2: Explicit boundary (for cross-CF federation)
# orgs: ["remote-cf-org-guid-1", "remote-cf-org-guid-2"]
# OR
# spaces: ["remote-cf-space-guid-1"]Validation rules:
authorization.config.scopeis mutually exclusive withauthorization.config.orgsandauthorization.config.spacesauthorization.config.orgsis mutually exclusive withauthorization.config.spaces- If
authorization.configis omitted, the default isscope: any(any authenticated caller passes domain-level checks) authorization.mode: cf_identityrequiresxfcc.identity_extractor: cf_ou- Invalid combinations are rejected during BOSH deployment by the GoRouter job templates
How scope works:
GoRouter's route table stores per-endpoint tags from the route-emitter, including organization_id and space_id for each destination app instance. When scope is set, GoRouter compares the caller's identity (extracted from the mTLS certificate) against the destination's tags:
| Scope | Check | Effect |
|---|---|---|
any |
None | Any authenticated caller passes domain-level checks |
org |
caller.OrgGUID ∈ pool endpoints' organization_id |
Caller must be from the same org as the destination |
space |
caller.SpaceGUID ∈ pool endpoints' space_id |
Caller must be from the same space as the destination |
Shared routes and endpoint pools:
When a shared route has apps mapped from multiple spaces, the GoRouter EndpointPool for that route contains endpoints from different spaces. Each endpoint carries its own space_id and organization_id tags, set by the route-emitter based on the app instance it represents — not the route owner.
For example, if route api.apps.mtls.internal is shared between Space A and Space B, with an app mapped in each:
EndpointPool for "api.apps.mtls.internal":
[0] 10.0.1.5:8080 tags: { space_id: "space-a-guid", organization_id: "org-guid" }
[1] 10.0.2.9:8080 tags: { space_id: "space-b-guid", organization_id: "org-guid" }
GoRouter iterates the pool's endpoints when evaluating scope, checking the caller's identity against each endpoint's tags and short-circuiting on the first match. For scope: space, if any endpoint's space_id matches the caller's space GUID, the request is allowed. A caller from Space A or Space B passes the check; a caller from Space C (with no app mapped to the route) is denied. This naturally enables cross-space access on shared routes between the participating spaces.
When xfcc.identity_extractor: cf_ou and authorization.mode: cf_identity are enabled, GoRouter enforces access control at the routing layer using a default-deny model, matching the design of container-to-container network policies.
Authorization is enforced at two layers:
- Domain level (operator): Configured via
authorization.configinmtls_domains - Route level (developer): Configured via the Cloud Controller Access Policy API
Layered authorization:
flowchart LR
A[Request on mTLS domain] --> B["1. Domain authorization (operator)"]
B --> C["2. Route authorization (developer)"]
C --> D[Request forwarded with XFCC header]
Developers can only restrict further within operator boundaries. They cannot expand access beyond operator-defined limits.
Developers manage route-level access policies through the Cloud Controller V3 API. This provides a dedicated endpoint for managing which applications, spaces, or organizations are allowed to call mTLS-protected routes.
API Endpoints:
| Method | Path | Description |
|---|---|---|
GET |
/v3/routes/:route_guid/access_policies |
List access policies for a route |
POST |
/v3/routes/:route_guid/access_policies |
Create access policies |
DELETE |
/v3/routes/:route_guid/access_policies/:policy_guid |
Delete a policy |
Create Request:
{
"policies": [
{
"source": {
"type": "app",
"guid": "frontend-app-guid"
}
},
{
"source": {
"type": "space",
"guid": "trusted-space-guid"
}
},
{
"source": {
"type": "org",
"guid": "partner-org-guid"
}
},
{
"source": {
"type": "any"
}
}
]
}Response:
{
"resources": [
{
"guid": "policy-guid-1",
"created_at": "2026-03-25T10:00:00Z",
"updated_at": "2026-03-25T10:00:00Z",
"source": {
"type": "app",
"guid": "frontend-app-guid"
},
"links": {
"self": { "href": "/v3/routes/route-guid/access_policies/policy-guid-1" },
"route": { "href": "/v3/routes/route-guid" }
}
}
]
}Source Types:
| Type | Description |
|---|---|
app |
Allow a specific application (by GUID) |
space |
Allow all applications in a space |
org |
Allow all applications in an organization |
any |
Allow any authenticated CF application (within operator scope) |
Design rationale:
This API design is aligned with the C2C network policy server API but follows a destination-controlled model rather than C2C's bilateral model. Route owners define who can call them; callers don't need to opt in.
Validation rules:
- Access policies can only be created for routes on mTLS-enabled domains (
domain.mtls_enabled: true) anytype is mutually exclusive with specific source types (cannot combineanywithapp/space/org)- Source GUIDs are not validated against the local database to support cross-CF federation scenarios
- Duplicate policies (same route + source type + source GUID) are handled idempotently (existing policy returned)
Authorization:
Only Space Developers in the route's space can manage access policies. Unlike C2C policies which require permissions in both source and destination spaces, mTLS access policies are destination-controlled.
Cloud Controller stores access policies in a dedicated route_access_policies table. When syncing route information to Diego, Cloud Controller merges these policies into route options:
# Access policies are converted to RFC-0027 compliant route options
route.options = {
"mtls_allowed_apps": "app-guid-1,app-guid-2",
"mtls_allowed_spaces": "space-guid-1",
"mtls_allowed_orgs": "org-guid-1",
"mtls_allow_any": true
}This conversion happens transparently—developers interact only with the Access Policy API, not with raw route options.
Warning behavior:
When a route has access policies but the domain has authorization.mode: none, GoRouter logs a warning per-request to the application's log stream (see Router Log Messages for the full format):
[RTR] backend.partner.example.com - mtls_auth:"not_enforced"
mtls_denied_reason:"route has access policies but domain authorization.mode=none; rules ignored"
The request is forwarded, not denied. This allows developers to configure policies before the operator enables enforcement, and provides visible feedback that the rules are not yet active.
This builds on the route options framework from RFC-0027: Generic Per-Route Features. Phase 1b depends on RFC-0027 being implemented first.
To simplify client adoption, add an HTTP proxy to the application sidecar that automatically handles mTLS. Users enable this per-app; applications that configure TLS clients directly do not need it.
How it works:
- Diego configures an egress proxy (Envoy) listening on
127.0.0.1:8888 - The proxy is configured to intercept requests to
*.apps.mtls.internal - For matching requests, the proxy:
- Upgrades the connection to TLS
- Presents the application's instance identity certificate
- Forwards the request to GoRouter
Application usage:
# Client app sets HTTP_PROXY for the internal domain
export HTTP_PROXY=http://127.0.0.1:8888
export NO_PROXY=external-api.example.com
# Plain HTTP request, proxy handles mTLS automatically
curl http://myservice.apps.mtls.internal/apiThis eliminates the need for applications to load certificates and configure TLS clients.
The xfcc.identity_extractor and authorization.mode fields are designed to support additional modes in the future without breaking the configuration schema:
| Identity Extractor | Authorization Mode | Use Case |
|---|---|---|
none |
none |
External client certs, app-level authorization |
cf_ou |
cf_identity |
CF app-to-app with platform-enforced rules |
cf_ou |
cf_identity |
Cross-CF federation (via per-installation domains) |
subject_cn (future) |
cn_allowlist (future) |
Generic CN-based authorization |
spiffe (future) |
spiffe_authz (future) |
SPIFFE identity federation |
Each authorization.mode can define its own authorization.config schema, allowing future modes to have different policy options without affecting existing configurations.
This allows operators to use mtls_domains for external client certificate validation without CF-specific coupling, while preserving the option to add new identity extraction and authorization modes as needs evolve.
For CF app-to-app routing use case:
Phase 1a and Phase 1b (with xfcc.identity_extractor: cf_ou and authorization.mode: cf_identity) are co-requisites and must be released together.
Deploying Phase 1a without enabling CF identity authorization would leave all mTLS routes accessible to any authenticated app, violating the default-deny security model. Routes must have access policies configured via the Cloud Controller API to control access.
Phase 1b depends on RFC-0027: Generic Per-Route Features being implemented first.
For external client validation use case:
Phase 1a alone (with authorization.mode: none) is sufficient. Backend applications handle authorization based on the XFCC header.
GoRouter emits [RTR] log lines to the application's log stream (visible via cf logs). The following messages cover mTLS authorization scenarios, including edge cases where access policies exist but authorization is not enforced.
Successful authorized request:
When a request passes both domain-level and route-level authorization:
[RTR] backend.apps.mtls.internal - [2026-03-20T10:15:00Z]
"GET /api/data HTTP/1.1" 200 1234
x_forwarded_for:"10.0.1.5" x_forwarded_proto:"https"
caller_app:"frontend-guid" caller_space:"space-guid" caller_org:"org-guid"
mtls_auth:"allowed" mtls_rule:"route:mtls_allowed_apps"
The caller_* fields are extracted from the instance identity certificate. mtls_auth:"allowed" confirms authorization passed, and mtls_rule identifies which rule matched.
Denied — failed domain-level scope check:
When the caller's identity does not match the operator's scope boundary:
[RTR] backend.apps.mtls.internal - [2026-03-20T10:15:01Z]
"GET /api/data HTTP/1.1" 403 0
caller_app:"attacker-guid" caller_space:"other-space-guid" caller_org:"other-org-guid"
mtls_auth:"denied" mtls_rule:"domain:scope=org"
mtls_denied_reason:"caller org other-org-guid not in endpoint pool"
Denied — failed route-level access policy check:
When the caller passes domain-level checks but has no matching access policy:
[RTR] backend.apps.mtls.internal - [2026-03-20T10:15:02Z]
"GET /api/data HTTP/1.1" 403 0
caller_app:"unknown-app-guid" caller_space:"same-space-guid" caller_org:"same-org-guid"
mtls_auth:"denied" mtls_rule:"route:mtls_allowed_apps"
mtls_denied_reason:"caller app unknown-app-guid not in mtls_allowed_apps"
Denied — no access policies configured (default deny):
When a route on an mTLS domain has no access policies configured, the default-deny model rejects all requests:
[RTR] backend.apps.mtls.internal - [2026-03-20T10:15:03Z]
"GET /api/data HTTP/1.1" 403 0
caller_app:"frontend-guid" caller_space:"space-guid" caller_org:"org-guid"
mtls_auth:"denied" mtls_rule:"route:no_access_policies"
mtls_denied_reason:"route has no access policies configured"
Warning — access policies configured but domain authorization not enabled:
When a route has access policies but the domain uses authorization.mode: none (or the route is on a non-mTLS domain), GoRouter logs a warning on each request. The request is forwarded (not denied) because authorization is not active:
[RTR] backend.partner.example.com - [2026-03-20T10:15:04Z]
"GET /api/data HTTP/1.1" 200 1234
mtls_auth:"not_enforced"
mtls_denied_reason:"route has access policies but domain authorization.mode=none; rules ignored"
This warning is logged per request (not just at startup) so it appears in the application's log stream, making it visible to developers who may have misconfigured their route. Cloud Controller stores the access policies regardless—they become active when the operator enables authorization.mode: cf_identity on the domain.
Warning — identity extraction failed:
When the client certificate is valid but does not contain the expected identity fields:
[RTR] backend.apps.mtls.internal - [2026-03-20T10:15:05Z]
"GET /api/data HTTP/1.1" 403 0
mtls_auth:"denied" mtls_rule:"identity_extraction"
mtls_denied_reason:"certificate does not contain CF identity OU fields"
Summary of mtls_auth values:
| Value | HTTP Status | Meaning |
|---|---|---|
allowed |
2xx/3xx/5xx | Request authorized and forwarded to backend |
denied |
403 | Request rejected by GoRouter |
not_enforced |
2xx/3xx/5xx | Route has access policies but domain does not enforce them |
This RFC complements Cloud Foundry's existing container-to-container (C2C) networking rather than replacing it. The two mechanisms serve different purposes and operate at different layers.
Why extend GoRouter instead of C2C networking?
This RFC reuses existing GoRouter infrastructure—TLS termination, request routing, load balancing, access logging, and the route options framework from RFC-0027. By enforcing authorization at the HTTP layer, applications gain access to caller identity via the XFCC header, enabling fine-grained authorization decisions. GoRouter already handles millions of requests; adding per-domain mTLS builds on proven infrastructure.
C2C networking operates at Layer 4 (TCP/UDP) using IPtables rules enforced on Diego Cells via VXLAN policy agents. This architecture has scaling considerations for large deployments: policies are limited by VXLAN's 16-bit marks (~65,535 apps can participate in policies), and each policy requires IPtables rules on every Diego Cell. For HTTP traffic requiring caller identity, load balancing, and observability, GoRouter-based routing is a better fit.
When to use which:
- C2C networking: Non-HTTP protocols (databases, message queues, gRPC over TCP), low-latency direct connections, when traffic should bypass GoRouter entirely.
- mTLS app routing (this RFC): HTTP APIs requiring caller identity in the request, platform-enforced authorization at the route level, when you need GoRouter features (load balancing, retries, observability, access logs).
The two mechanisms can coexist. An application might use C2C networking for database connections while exposing HTTP APIs via mTLS app routing.
Authorization model differences:
C2C network policies and this RFC's access policies have different authorization semantics:
- C2C: A user creates a network policy allowing App A → App B. The user must have the
network.writescope (or Space Developer role withenable_space_developer_self_service) in both the source and destination spaces. The policy is directional and names specific source/destination pairs. - Access policies (this RFC): The operator boundary allows callers within the configured scope. The developer creates access policies on their own route via Cloud Controller — they only need permissions in the destination space. There is no requirement for the caller's space to opt in.
This is intentional. This RFC's model is destination-controlled: the route owner decides who may call them, and the operator sets the maximum boundary. This matches how HTTP APIs typically work — the server defines its access policy. C2C's bilateral model (both sides must agree) is appropriate for Layer 4 network-level access where neither side is inherently the "server."
Operators who want the bilateral guarantee of C2C should continue using C2C networking for those workloads. The two are complementary.
Operators must mark domains as mTLS-enabled in Cloud Controller for developers to create access policies:
# Enable mTLS on a domain
cf curl -X PATCH /v3/domains/domain-guid -d '{"mtls_enabled": true}'This flag is stored in the domains table and enforces that access policies can only be created for routes on mTLS-enabled domains.
CF app-to-app routing (same-org boundary):
router:
mtls_domains:
- domain: "*.apps.mtls.internal"
ca_certs: ((diego_instance_identity_ca.certificate))
forwarded_client_cert: sanitize_set
xfcc:
format: envoy
identity_extractor: cf_ou
authorization:
mode: cf_identity
config:
# Caller must be from the same org as the route's destination app.
# No org GUIDs needed — GoRouter checks the caller's certificate
# against the route-emitter tags on each endpoint.
scope: orgCF app-to-app routing (same-space boundary):
router:
mtls_domains:
- domain: "*.apps.mtls.internal"
ca_certs: ((diego_instance_identity_ca.certificate))
forwarded_client_cert: sanitize_set
xfcc:
format: envoy
identity_extractor: cf_ou
authorization:
mode: cf_identity
config:
# Caller must be from the same space as the route's destination app.
# With shared routes, callers from any participating space (i.e. any
# space that has an app mapped to the route) are allowed.
scope: spaceCF app-to-app routing (any authenticated caller):
router:
mtls_domains:
- domain: "*.apps.mtls.internal"
ca_certs: ((diego_instance_identity_ca.certificate))
forwarded_client_cert: sanitize_set
xfcc:
format: envoy
identity_extractor: cf_ou
authorization:
mode: cf_identity
# No config or scope: any — any authenticated caller passes domain-level checks
# Route-level access policies control accessApplication access policy configuration:
Developers configure access policies via the Cloud Controller API:
# Allow specific apps to call a route
cf curl -X POST /v3/routes/route-guid/access_policies -d '{
"policies": [
{"source": {"type": "app", "guid": "frontend-app-guid"}},
{"source": {"type": "app", "guid": "monitoring-app-guid"}}
]
}'
# Allow all apps in a space
cf curl -X POST /v3/routes/route-guid/access_policies -d '{
"policies": [
{"source": {"type": "space", "guid": "trusted-space-guid"}}
]
}'
# Allow any authenticated app (within operator scope)
cf curl -X POST /v3/routes/route-guid/access_policies -d '{
"policies": [
{"source": {"type": "any"}}
]
}'
# List access policies
cf curl /v3/routes/route-guid/access_policies
# Delete a specific policy
cf curl -X DELETE /v3/routes/route-guid/access_policies/policy-guidExternal client certificate validation (app-level authorization):
router:
mtls_domains:
- domain: "*.partner.example.com"
ca_certs: ((partner_ca.certificate))
forwarded_client_cert: sanitize_set
xfcc:
format: envoy
# identity_extractor: none (default)
authorization:
mode: none
# No config needed for mode: noneIn this configuration, GoRouter validates that the client certificate is signed by the partner CA, then forwards the XFCC header to the backend application. The application parses the XFCC header and performs its own authorization based on the certificate's Subject, SANs, or other fields.
Cross-CF federation (apps calling across CF installations):
When multiple CF installations need to communicate, configure a separate mTLS domain per remote CF installation. This uses explicit orgs:/spaces: lists rather than scope: because org/space GUIDs from a remote CF are meaningless locally — there are no local route-emitter tags to match against. Each remote installation's CA is trusted independently:
router:
mtls_domains:
# Local CF app-to-app (scope uses route-emitter tags)
- domain: "*.apps.mtls.internal"
ca_certs: ((diego_instance_identity_ca.certificate))
forwarded_client_cert: sanitize_set
xfcc:
format: envoy
identity_extractor: cf_ou
authorization:
mode: cf_identity
config:
scope: org # Callers must be in same org as destination
# Trust apps from CF-East installation
# Uses explicit orgs: list because remote GUIDs have no local route-emitter tags
- domain: "*.apps.mtls.cf-east.internal"
ca_certs: ((cf_east_diego_ca.certificate))
forwarded_client_cert: sanitize_set
xfcc:
format: envoy
identity_extractor: cf_ou
authorization:
mode: cf_identity
config:
orgs: ["trusted-east-org-guid"] # Only this org from CF-East can call
# Trust apps from CF-West installation
# No explicit list: any CF-West app can call (route-level access policies apply)
- domain: "*.apps.mtls.cf-west.internal"
ca_certs: ((cf_west_diego_ca.certificate))
forwarded_client_cert: sanitize_set
xfcc:
format: envoy
identity_extractor: cf_ou
authorization:
mode: cf_identity
# No config: any CF-West app can call (route-level access policies apply)Access policies for cross-CF federation:
# Allow specific apps from CF-East to call a route
cf curl -X POST /v3/routes/route-guid/access_policies -d '{
"policies": [
{"source": {"type": "app", "guid": "east-frontend-guid"}}
]
}'The domain naming convention *.apps.mtls.<cf-installation>.internal ensures:
- No conflict with existing app routes (CF identifier is at the parent domain level)
- GUIDs are scoped to their originating installation
- Each installation's CA is trusted independently
- Standard
cf_ouidentity extraction andcf_identityauthorization work unchanged - Local domains use
scope:(matches route-emitter tags); remote domains use explicitorgs:/spaces:lists
| Component | Reference |
|---|---|
| GoRouter TLS config | routing-release/.../config.go |
| GoRouter BOSH spec | routing-release/jobs/gorouter/spec |
| RFC-0027 route options | toc/rfc/rfc-0027-generic-per-route-features.md |
| Cloud Controller routes | cloud_controller_ng/.../route.rb |
| Container-to-Container Networking | CF Docs |
| C2C Policy Server API | cf-networking-release/docs/08-policy-server-api.md |
| Diego Instance Identity | diego-release/docs/050-app-instance-identity.md |