Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
d3ab855
Add per-domain mTLS configuration support to GoRouter config
rkoster Mar 4, 2026
012071b
Implement per-domain TLS configuration via GetConfigForClient
rkoster Mar 4, 2026
1032c7d
Make clientcert handler domain-aware
rkoster Mar 4, 2026
3ff36fe
Add BOSH configuration support for mTLS domains
rkoster Mar 4, 2026
8edbccd
Add AllowedSources support for mTLS authorization (Phase 1b partial)
rkoster Mar 4, 2026
72428d2
Copy AllowedSourceAppGUIDs in NewEndpoint constructor
rkoster Mar 4, 2026
5950fc0
Add identity extraction handler for mTLS caller identification
rkoster Mar 4, 2026
d8a4d09
Add mTLS authorization handler for app-to-app access control
rkoster Mar 4, 2026
c0cd088
Wire identity and authorization handlers into proxy chain
rkoster Mar 4, 2026
4614259
Add AllowedSourceAppGUIDs support to route-registrar
rkoster Mar 4, 2026
76db306
Fix domain names to match RFC specification
rkoster Mar 4, 2026
0fadbd7
Expand AllowedSources to full RFC specification
rkoster Mar 4, 2026
306714e
Add comprehensive integration tests for mTLS app-to-app routing
rkoster Mar 4, 2026
61faa43
Fix mTLS authorization to use RoutePool instead of RouteEndpoint
rkoster Mar 5, 2026
480023b
Support allowed_sources nested in options for CAPI/Diego integration
rkoster Mar 5, 2026
baabb50
Fix identity extraction to handle GoRouter XFCC format (raw base64)
rkoster Mar 5, 2026
37b6a12
Rename AllowedSources to MtlsAllowedSources for clarity
rkoster Mar 5, 2026
1095b70
Add configurable XFCC format support (raw/envoy)
rkoster Mar 5, 2026
811869e
Emit RTR access logs for denied mTLS requests
rkoster Mar 5, 2026
fd3d17e
Refactor mTLS route options to RFC-0027 compliant flat format
rkoster Mar 5, 2026
899e6aa
Implement RFC domain-scoped mTLS app-to-app routing in GoRouter
rkoster Apr 3, 2026
84e3db2
feat(gorouter): implement RFC-compliant post-selection mTLS authoriza…
rkoster Apr 16, 2026
68b17b2
refactor: rename MtlsAuthError to AuthError for future extensibility
rkoster Apr 16, 2026
687fe93
refactor: extract shared mTLS helper functions to mtls_helpers.go
rkoster Apr 16, 2026
d690778
refactor: remove deprecated mtls_authorization handler
rkoster Apr 16, 2026
57e4153
refactor: move helper functions to their respective handlers
rkoster Apr 16, 2026
22d1eb6
refactor: introduce AuthResult and remove mTLS-specific naming
rkoster Apr 17, 2026
fd7e98b
refactor: rename test variable mtlsErr to authErr for consistency
rkoster Apr 17, 2026
5849c6e
refactor: rename mtlsAllowedSources parameter to allowedSources in te…
rkoster Apr 17, 2026
cdbb486
refactor: align integration test naming with RFC terminology
rkoster Apr 17, 2026
d987d3d
refactor: remove unused EndpointPool methods from deprecated pre-sele…
rkoster Apr 17, 2026
e72b52d
refactor: remove identity-aware routing fields from route-registrar
rkoster Apr 17, 2026
4df9d74
chore: add devbox files to .gitignore
rkoster Apr 17, 2026
964c6a2
fix: run gofmt on post_selection_pipeline_test.go
rkoster Apr 17, 2026
f9cee18
fix: run gofmt on all modified Go files
rkoster Apr 17, 2026
f21ae09
fix: resolve go vet and staticcheck issues
rkoster Apr 17, 2026
682bbb6
fix: resolve integration test failures for identity-aware routing
rkoster Apr 20, 2026
28b7e1b
fix: run gofmt on modified files
rkoster Apr 20, 2026
b8342cd
chore: trigger CI after rebase on develop
rkoster Apr 20, 2026
f2269df
fix: stop router before NATS in integration test cleanup
rkoster Apr 20, 2026
1d4f0f7
chore: trigger CI for port conflict fix
rkoster Apr 20, 2026
59d4260
refactor: rebrand access rules to route policies terminology
rkoster Apr 21, 2026
04a99e4
fix: apply gofmt to test files for CI compliance
rkoster Apr 21, 2026
29085ca
fix: update integration test to use renamed struct fields
rkoster Apr 21, 2026
2306ecb
fix: route policy enforcement on routes without enforcement enabled
rkoster Apr 22, 2026
c50bb24
fix: strip port from Host header before mTLS domain matching
rkoster Apr 22, 2026
054ed35
fix: apply gofmt to mtls_route_policies_auth_test.go
rkoster Apr 23, 2026
b68ca47
fix(test): correct expectations for routes without enforcement enabled
rkoster Apr 23, 2026
f22798d
fix: address PR #535 code review findings
rkoster May 4, 2026
baea967
fix: resolve PR #535 code review findings
rkoster May 4, 2026
d9b86fc
fix: address critical security and correctness issues in mTLS routing
rkoster May 4, 2026
a3f0b45
fix: add missing tests and fix AuthError dead-code path in proxy pipe…
rkoster May 6, 2026
d6e369b
fix: reject always_forward+xfcc_format combination at deploy time
rkoster May 6, 2026
4bdb317
Validate xfcc_format + always_forward conflict at Go config level
rkoster May 6, 2026
7f8d9a0
go mod tidy && go mod vendor
rkoster May 12, 2026
04afb2b
fix: add missing locket/lock, cactus/go-statsd-client and grpc/transp…
rkoster May 13, 2026
141928b
fix: always emit identity fields in access logs with renamed keys
rkoster May 26, 2026
38c6ada
fix: downgrade per-request auth denial logs from INFO to DEBUG
rkoster May 26, 2026
db58685
fix: add cross-references to spec descriptions and ERB template valid…
rkoster May 26, 2026
a9410b2
fix: address PR #535 review findings for identity handler
rkoster May 26, 2026
2f78d4b
fix: split MtlsPreAuth handler to resolve identity extraction regression
rkoster May 27, 2026
45e7abd
test: add unit tests for pool-level RoutePolicyScope and RoutePolicies
rkoster May 27, 2026
8bc0718
fix: make mTLS domain matching case-insensitive per RFC 1035
rkoster May 27, 2026
ca770cf
fix: use endpoint-level route policies for per-endpoint authorization
rkoster May 27, 2026
d762fd8
fix: complete case-insensitive mTLS domain matching per RFC 1035
rkoster May 28, 2026
cb78473
fix: remove per-request log statements to comply with gorouter loggin…
rkoster May 28, 2026
5ee42de
feat: return no-op handlers when no mTLS domains configured
rkoster May 28, 2026
a2e1cdb
style: gofmt mtls_route_policies_auth_test.go
rkoster May 28, 2026
eba1576
feat: include route_policy_scope and route_policies in /routes endpoi…
rkoster May 29, 2026
6e1128e
fix: move mTLS access log fields to extra_access_log_fields opt-in
rkoster Jun 4, 2026
af99f8e
fix: add missing processMtlsDomains error tests and normalize casing …
rkoster Jun 4, 2026
61ec244
test: add handler tests for identity-aware access log fields
rkoster Jun 4, 2026
bd4ecb0
refactor: extract post-selection auth into postselection package
rkoster Jun 10, 2026
cc16961
fix: add postselection package to gorouter package spec
rkoster Jun 10, 2026
686f78f
test: use specific TLS error strings in integration tests
rkoster Jun 12, 2026
e367664
test: remove invalid per-endpoint route policy integration test
rkoster Jun 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,8 @@ tags
src/golang.org/x/tools/
src/github.com/kisielk/
src/golang.org/x/sync/

# Devbox local development environment
devbox.json
devbox.lock
.devbox/
31 changes: 30 additions & 1 deletion jobs/gorouter/spec
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ properties:
none - Gorouter will not request client certificates in TLS handshakes, and will ignore them if presented. Incompatible with `forwarded_client_cert: forward` or `sanitize_set`.
request - Gorouter will request client certificates in TLS handshakes, and will validate them when presented, but will not require them.
require - Gorouter will fail a TLS handshake if the client does not provide a certificate signed by a CA it trusts. Select this option if your load balancer terminates TLS and does not require client certificates, and the load balancer provides a compatible client certificate of its own to Gorouter in an independent TLS handshake. This option may also be selected for Isolation Segments when Gorouter is the first point of TLS termination. Many clients of CF platform APIs do not present client certificates in TLS handshakes, so the first point of TLS termination for requests to the system domain must not require them. This option has no effect on the HTTP listener; to disable HTTP support set `disable_http: true`.

Note: This property applies to the default TLS listener. Domains configured in `router.domains` enforce their own mTLS requirement independently — client certificates are always required for those domains regardless of this setting.
default: request
router.disable_http:
description: Disables the http listener on port specified by router.port. This cannot be set to true if enable_ssl is false.
Expand Down Expand Up @@ -200,6 +202,33 @@ properties:
router.only_trust_client_ca_certs:
description: "When router.only_trust_client_ca_certs is true, router.client_ca_certs are the only trusted CA certs for client requests. When router.only_trust_client_ca_certs is false, router.client_ca_certs are trusted in addition to router.ca_certs and the CA certificates installed on the filesystem. This will have no affect if the `router.client_cert_validation` property is set to none."
default: false
router.domains:
description: |
Array of domains requiring mutual TLS authentication. Each domain can have its own CA certificate pool, forwarded_client_cert mode, and xfcc_format.
For non-wildcard domains, the domain must match the request host exactly.
For wildcard domains (e.g., *.apps.identity), the wildcard must be the leftmost label and matches any single label.
Comment thread
rkoster marked this conversation as resolved.

These domains enforce client certificate validation independently of `router.client_cert_validation` — clients connecting to these domains are always required to present a valid certificate signed by the domain's configured CA.

xfcc_format controls the format of the X-Forwarded-Client-Cert header:
- "raw" (default): Full base64-encoded certificate (~1.5KB)
- "envoy": Compact Hash=<sha256>;Subject="<DN>" format (~300 bytes)
default: []
example:
- name: "*.apps.identity"
ca_certs: |
-----BEGIN CERTIFICATE-----
<CA certificate for apps.identity domain>
-----END CERTIFICATE-----
forwarded_client_cert: sanitize_set
xfcc_format: envoy
- name: "secure.example.com"
ca_certs: |
-----BEGIN CERTIFICATE-----
<CA certificate for secure.example.com>
-----END CERTIFICATE-----
forwarded_client_cert: forward
xfcc_format: raw
router.backends.max_attempts:
description: |
Maximum number of attempts on failing requests against backend routes.
Expand Down Expand Up @@ -339,7 +368,7 @@ properties:
this property and operators have to explicitly enable them. This is done to prevent breaking
log parsing in existing setups by the introduction of new fields. Does not affect stdout /
stderr logs.
Available fields are: backend_time, dial_time, dns_time, failed_attempts, failed_attempts_time, local_address, tls_time
Available fields are: backend_time, caller_cf_app, caller_cf_org, caller_cf_space, dial_time, dns_time, failed_attempts, failed_attempts_time, local_address, route_policy, tls_sni, tls_time
default: []
router.enable_proxy:
description: "Enables support for the popular PROXY protocol, allowing downstream load balancers that do not support HTTP to pass along client information."
Expand Down
51 changes: 51 additions & 0 deletions jobs/gorouter/templates/gorouter.yml.erb
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,57 @@ if p('router.client_ca_certs')
params['client_ca_certs'] = client_ca_certs
end

if_p('router.domains') do |domains|
if !domains.is_a?(Array)
raise 'router.domains must be provided as an array'
end
Comment thread
rkoster marked this conversation as resolved.

processed_domains = []
domains.each do |domain_config|
if !domain_config.is_a?(Hash)
raise 'Each entry in router.domains must be a hash'
end
Comment thread
rkoster marked this conversation as resolved.

if !domain_config.key?('name') || domain_config['name'].nil? || domain_config['name'].strip.empty?
raise 'Each entry in router.domains must have a "name" key'
Comment thread
rkoster marked this conversation as resolved.
end

if !domain_config.key?('ca_certs') || domain_config['ca_certs'].nil? || domain_config['ca_certs'].strip.empty?
Comment thread
rkoster marked this conversation as resolved.
raise 'Each entry in router.domains must have a "ca_certs" key with certificate content'
Comment thread
rkoster marked this conversation as resolved.
end

processed_entry = {
'domain' => domain_config['name'],
'ca_certs' => domain_config['ca_certs']
}

if domain_config.key?('forwarded_client_cert') && !domain_config['forwarded_client_cert'].nil?
valid_modes = ['always_forward', 'forward', 'sanitize_set']
mode = domain_config['forwarded_client_cert'].downcase
unless valid_modes.include?(mode)
raise "Invalid forwarded_client_cert mode '#{mode}' for domain '#{domain_config['name']}'. Must be one of: #{valid_modes.join(', ')}"
end
processed_entry['forwarded_client_cert'] = mode
end
Comment thread
rkoster marked this conversation as resolved.

if domain_config.key?('xfcc_format') && !domain_config['xfcc_format'].nil?
valid_formats = ['raw', 'envoy']
format = domain_config['xfcc_format'].downcase
unless valid_formats.include?(format)
raise "Invalid xfcc_format '#{format}' for domain '#{domain_config['name']}'. Must be one of: #{valid_formats.join(', ')}"
end
Comment thread
rkoster marked this conversation as resolved.
if processed_entry['forwarded_client_cert'] == 'always_forward'
raise "xfcc_format has no effect for domain '#{domain_config['name']}' when forwarded_client_cert is 'always_forward'. Remove xfcc_format or change forwarded_client_cert to 'sanitize_set'."
end
processed_entry['xfcc_format'] = format
end

processed_domains << processed_entry
end

params['domains'] = processed_domains
end

if_p('router.http_rewrite') do |r|
params['http_rewrite'] = r
end
Expand Down
1 change: 1 addition & 0 deletions packages/gorouter/spec
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ files:
- code.cloudfoundry.org/gorouter/errorwriter/*.go # gosub
- code.cloudfoundry.org/gorouter/fakes/*.go # gosub
- code.cloudfoundry.org/gorouter/handlers/*.go # gosub
- code.cloudfoundry.org/gorouter/handlers/postselection/*.go # gosub
- code.cloudfoundry.org/gorouter/integration/*.go # gosub
- code.cloudfoundry.org/gorouter/logadapter/*.go # gosub
- code.cloudfoundry.org/gorouter/logger/*.go # gosub
Expand Down
2 changes: 1 addition & 1 deletion packages/routing-api/spec
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ files:
- code.cloudfoundry.org/vendor/code.cloudfoundry.org/lager/v3/internal/truncate/*.go # gosub
- code.cloudfoundry.org/vendor/code.cloudfoundry.org/lager/v3/lagerflags/*.go # gosub
- code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/*.go # gosub
- code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/lock/*.go # gosub
- code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/cmd/locket/certauthority/*.go # gosub
- code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/cmd/locket/config/*.go # gosub
- code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/cmd/locket/testrunner/*.go # gosub
- code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/lock/*.go # gosub
- code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/models/*.go # gosub
- code.cloudfoundry.org/routing-api/*.go # gosub
- code.cloudfoundry.org/routing-api/admin/*.go # gosub
Expand Down
Loading