A simple Go application to test X-Forwarded-Client-Cert (XFCC) header format in Cloud Foundry environments with mTLS app-to-app routing.
This tool verifies that GoRouter correctly implements the Envoy XFCC format when routing requests over mTLS domains. It checks whether the XFCC header contains:
- ✅ Envoy format:
Hash=<hash>;Subject="<subject>";URI=<uri> - ❌ Raw PEM certificate (bug):
Cert="-----BEGIN CERTIFICATE-----\n..."
- Cloud Foundry deployment with mTLS app-to-app routing enabled
- mTLS domain configured (e.g.,
*.apps.identity) - CF CLI with route policy plugin (for authorization)
- Go buildpack available in your CF deployment
main.go- Go HTTP server with XFCC testing endpointsgo.mod- Go module definitionmanifest.yml- CF deployment manifestREADME.md- This file
Create a directory and save all files:
mkdir xfcc-tester
cd xfcc-tester
# Save main.go, go.mod, and manifest.yml hereEdit manifest.yml if your mTLS domain is different from apps.identity:
routes:
- route: xfcc-tester.YOUR-MTLS-DOMAINcf pushThe app will:
- Build using the Go buildpack
- Deploy to the mTLS domain
- Start listening on the assigned PORT
Allow the app to call itself over mTLS:
# Get the app GUID
APP_GUID=$(cf app xfcc-tester --guid)
# Add route policy (allows app to call itself)
cf add-route-policy xfcc-tester.apps.identity \
--hostname xfcc-tester \
--source-app xfcc-testerNote: Route policies take ~30 seconds to propagate to all GoRouters.
Wait 30 seconds after adding the route policy, then test:
# From inside the container
cf ssh xfcc-tester -c "curl -s http://localhost:8080/test-xfcc" | jq .
# Expected output:
# {
# "status": "success",
# "my_route": "xfcc-tester.apps.identity",
# "echo_response": {
# "has_xfcc": true,
# "xfcc_header": "Hash=...;Subject=\"CN=...,OU=app:...\""
# }
# }Home page with links to all endpoints.
Returns the XFCC header received in the request.
Response:
{
"xfcc_header": "Hash=...;Subject=\"...\"",
"has_xfcc": true
}Makes an mTLS request to itself via GoRouter and returns the XFCC header that GoRouter added.
Response:
{
"status": "success",
"my_route": "xfcc-tester.apps.identity",
"echo_response": {
"xfcc_header": "Hash=...;Subject=\"...\"",
"has_xfcc": true
}
}Shows environment variables for debugging.
- The app exposes
/echoendpoint that captures and returns theX-Forwarded-Client-Certheader - The
/test-xfccendpoint:- Uses Diego instance identity certificate (
CF_INSTANCE_CERT,CF_INSTANCE_KEY) - Makes HTTPS request to
https://xfcc-tester.apps.identity/echo - GoRouter intercepts the request, validates the mTLS cert, and adds/sets the XFCC header
- The
/echoendpoint receives the request and returns the XFCC header value
- Uses Diego instance identity certificate (
- The response shows what XFCC format GoRouter is using
{
"xfcc_header": "Hash=abc123...;Subject=\"CN=...,OU=app:...\""
}- Header contains structured
Hash=andSubject=fields - No raw PEM certificate included
- GoRouter is correctly implementing Envoy XFCC format
{
"xfcc_header": "Cert=\"-----BEGIN CERTIFICATE-----\\n...\\n-----END CERTIFICATE-----\";..."
}- Header contains
Cert=field with full PEM-encoded certificate - This is the bug described in the issue report
- Check logs:
cf logs xfcc-tester --recent - Ensure Go buildpack is available:
cf buildpacks - Verify the app has enough memory (128M minimum)
- Verify route policy was added:
cf route-policies - Wait 30 seconds for route policy to propagate
- Check route policy source and destination match the app GUID
- Verify the mTLS domain is configured in GoRouter
- Check GoRouter logs for routing errors
- Ensure Diego instance identity is enabled
- Verify BOSH DNS is resolving
*.apps.identityto router instances
- GoRouter may not be configured for mTLS on this domain
- Check
router.mtls_domainsin GoRouter job properties - Verify client certificate is being sent (check app logs)
The app uses these CF-provided environment variables:
PORT- HTTP server port (assigned by CF)CF_INSTANCE_CERT- Diego instance identity certificate pathCF_INSTANCE_KEY- Diego instance identity private key pathVCAP_APPLICATION- CF application metadata (for debugging)
This is a self-referencing test app:
- The app makes mTLS requests to itself via the GoRouter
- This allows testing XFCC without needing a separate backend app
- The route policy allows the app to authorize requests to itself
Public Domain / CC0
Created for testing Cloud Foundry mTLS app-to-app routing implementations.