Skip to content
Open
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
ec66336
Add per-domain mTLS configuration support to GoRouter config
rkoster Mar 4, 2026
ea1e38f
Implement per-domain TLS configuration via GetConfigForClient
rkoster Mar 4, 2026
0eaed38
Make clientcert handler domain-aware
rkoster Mar 4, 2026
2cd1169
Add BOSH configuration support for mTLS domains
rkoster Mar 4, 2026
340cc75
Add AllowedSources support for mTLS authorization (Phase 1b partial)
rkoster Mar 4, 2026
3e05993
Copy AllowedSourceAppGUIDs in NewEndpoint constructor
rkoster Mar 4, 2026
bb23e97
Add identity extraction handler for mTLS caller identification
rkoster Mar 4, 2026
f4e71aa
Add mTLS authorization handler for app-to-app access control
rkoster Mar 4, 2026
ddb564c
Wire identity and authorization handlers into proxy chain
rkoster Mar 4, 2026
0f046bb
Add AllowedSourceAppGUIDs support to route-registrar
rkoster Mar 4, 2026
7d30cc4
Fix domain names to match RFC specification
rkoster Mar 4, 2026
ef3db35
Expand AllowedSources to full RFC specification
rkoster Mar 4, 2026
f57b032
Add comprehensive integration tests for mTLS app-to-app routing
rkoster Mar 4, 2026
d2ea151
Fix mTLS authorization to use RoutePool instead of RouteEndpoint
rkoster Mar 5, 2026
15db825
Support allowed_sources nested in options for CAPI/Diego integration
rkoster Mar 5, 2026
9fbe03c
Fix identity extraction to handle GoRouter XFCC format (raw base64)
rkoster Mar 5, 2026
e15e32b
Rename AllowedSources to MtlsAllowedSources for clarity
rkoster Mar 5, 2026
d388fde
Add configurable XFCC format support (raw/envoy)
rkoster Mar 5, 2026
4bc5191
Emit RTR access logs for denied mTLS requests
rkoster Mar 5, 2026
25c70e8
Refactor mTLS route options to RFC-0027 compliant flat format
rkoster Mar 5, 2026
bbb9a81
Implement RFC domain-scoped mTLS app-to-app routing in GoRouter
rkoster Apr 3, 2026
581f047
feat(gorouter): implement RFC-compliant post-selection mTLS authoriza…
rkoster Apr 16, 2026
7b4eb36
refactor: rename MtlsAuthError to AuthError for future extensibility
rkoster Apr 16, 2026
f321f94
refactor: extract shared mTLS helper functions to mtls_helpers.go
rkoster Apr 16, 2026
e6343a1
refactor: remove deprecated mtls_authorization handler
rkoster Apr 16, 2026
943ef10
refactor: move helper functions to their respective handlers
rkoster Apr 16, 2026
6fe2a0b
refactor: introduce AuthResult and remove mTLS-specific naming
rkoster Apr 17, 2026
ac763a4
refactor: rename test variable mtlsErr to authErr for consistency
rkoster Apr 17, 2026
6f291fd
refactor: rename mtlsAllowedSources parameter to allowedSources in te…
rkoster Apr 17, 2026
81d30b5
refactor: align integration test naming with RFC terminology
rkoster Apr 17, 2026
aad4ecf
refactor: remove unused EndpointPool methods from deprecated pre-sele…
rkoster Apr 17, 2026
0a89935
refactor: remove identity-aware routing fields from route-registrar
rkoster Apr 17, 2026
bf1f0db
chore: add devbox files to .gitignore
rkoster Apr 17, 2026
9289dcf
fix: run gofmt on post_selection_pipeline_test.go
rkoster Apr 17, 2026
c29de97
fix: run gofmt on all modified Go files
rkoster Apr 17, 2026
d1d8529
fix: resolve go vet and staticcheck issues
rkoster Apr 17, 2026
e7a443a
fix: resolve integration test failures for identity-aware routing
rkoster Apr 20, 2026
424ef5f
fix: run gofmt on modified files
rkoster Apr 20, 2026
1bbc500
chore: trigger CI after rebase on develop
rkoster Apr 20, 2026
b20b974
fix: stop router before NATS in integration test cleanup
rkoster Apr 20, 2026
07e2cb1
chore: trigger CI for port conflict fix
rkoster Apr 20, 2026
4cf972b
refactor: rebrand access rules to route policies terminology
rkoster Apr 21, 2026
db70419
fix: apply gofmt to test files for CI compliance
rkoster Apr 21, 2026
fc1b477
fix: update integration test to use renamed struct fields
rkoster Apr 21, 2026
6c6b8fb
fix: route policy enforcement on routes without enforcement enabled
rkoster Apr 22, 2026
ce29a3c
fix: strip port from Host header before mTLS domain matching
rkoster Apr 22, 2026
3fe508b
fix: apply gofmt to mtls_route_policies_auth_test.go
rkoster Apr 23, 2026
06afa77
fix(test): correct expectations for routes without enforcement enabled
rkoster Apr 23, 2026
01316c7
fix: address PR #535 code review findings
rkoster May 4, 2026
3b4dbe1
fix: resolve PR #535 code review findings
rkoster May 4, 2026
f1f94cf
fix: address critical security and correctness issues in mTLS routing
rkoster May 4, 2026
b8f9aeb
fix: add missing tests and fix AuthError dead-code path in proxy pipe…
rkoster May 6, 2026
0069911
fix: reject always_forward+xfcc_format combination at deploy time
rkoster May 6, 2026
783fe04
Validate xfcc_format + always_forward conflict at Go config level
rkoster May 6, 2026
84395ca
go mod tidy && go mod vendor
rkoster May 12, 2026
0a83573
fix: add missing locket/lock, cactus/go-statsd-client and grpc/transp…
rkoster May 13, 2026
a383505
fix: always emit identity fields in access logs with renamed keys
rkoster May 26, 2026
a91d33b
fix: downgrade per-request auth denial logs from INFO to DEBUG
rkoster May 26, 2026
a32b0e7
fix: add cross-references to spec descriptions and ERB template valid…
rkoster May 26, 2026
49f5b6d
fix: address PR #535 review findings for identity handler
rkoster May 26, 2026
0da3a54
fix: split MtlsPreAuth handler to resolve identity extraction regression
rkoster May 27, 2026
94a81c4
test: add unit tests for pool-level RoutePolicyScope and RoutePolicies
rkoster May 27, 2026
846c45b
fix: make mTLS domain matching case-insensitive per RFC 1035
rkoster May 27, 2026
952b4f5
fix: use endpoint-level route policies for per-endpoint authorization
rkoster May 27, 2026
d3f4135
fix: complete case-insensitive mTLS domain matching per RFC 1035
rkoster May 28, 2026
f100947
fix: remove per-request log statements to comply with gorouter loggin…
rkoster May 28, 2026
a4c165a
feat: return no-op handlers when no mTLS domains configured
rkoster May 28, 2026
36868de
style: gofmt mtls_route_policies_auth_test.go
rkoster May 28, 2026
0c7d4ab
feat: include route_policy_scope and route_policies in /routes endpoi…
rkoster May 29, 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/
29 changes: 29 additions & 0 deletions 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
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']
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']
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
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
Loading