Tailscale, Iroh, and trusted HTTP proxy identity¶
The C++ adapters in tailscale_identity.h, iroh_identity.h, and
spiffe_proxy_identity.h turn
transport evidence into PeerIdentity; they do not make authorization
decisions. Enable them explicitly and apply an authentication policy such as
peer_identity_primary or require_peer_identity separately.
Every header adapter requires exact immediate-proxy IP addresses. Hostnames,
CIDRs, and source ranges are rejected. The backend must not be reachable around
that proxy, and the proxy must replace or remove client-supplied identity
headers. Raw duplicate headers and case-varied duplicates fail closed. Header
evidence has configured_proxy assurance.
Iroh behind an HTTP bridge¶
iroh_forwarded_header_provider consumes exactly one
VGI-Forwarded-Iroh-Endpoint value after the exact immediate-proxy IP check.
The value must be the canonical 64-character lowercase hexadecimal EndpointId;
uppercase, short, duplicate, case-varied duplicate, control-bearing, and
untrusted requests fail closed. The operator supplies the issuer locally.
The resulting stable endpoint identity has configured_proxy assurance and
original_assurance=cryptographic_peer: the adjacent bridge authenticated the
Iroh peer cryptographically, while the worker authenticates only its trusted
hop to that bridge. The backend must be unreachable except through the bridge,
which must strip any client-provided forwarding header before setting its own.
vgi_rpc::HttpConfig config;
config.peer_identity_providers.push_back(vgi_rpc::iroh_forwarded_header_provider(
{.issuer = "production-mesh", .trusted_proxy_addresses = {"127.0.0.1"}}));
config.peer_authentication_policy = vgi_rpc::peer_identity_primary("iroh");
Tailscale¶
tailscale_serve_identity_provider consumes Tailscale Serve user and
application-capability headers only after the exact proxy check. Funnel is not
identity evidence. Serve logins are verified but login-stable, so they are not
eligible for the built-in stable-subject primary policy. Capability-only
evidence remains subjectless. Values accept plain ASCII or strict RFC 2047
UTF-8 Q encoding; JSON capabilities are size/depth/count bounded, reject
duplicate keys, and require application-capability arrays of objects.
tailscale_localapi_identity_provider issues one fresh LocalAPI WhoIs request
per resolution. It never starts the CLI, caches WhoIs, follows redirects, or
uses proxy environment variables. On Unix, configure unix_socket, or omit it
to use /var/run/tailscale/tailscaled.sock. endpoint accepts an explicit
plain-HTTP origin such as a macOS same-user-proof endpoint; password becomes
Basic auth with an empty username. Requests use Host: local-tailscaled.sock,
scope capabilities with svc_name or dst_ip, and are bounded by both the
provider timeout and resolution deadline. Responses have bounded headers,
body, JSON depth, and JSON values.
WhoIs assigns stable user:<numeric UserProfile.ID> subjects to untagged nodes.
Tagged nodes ignore UserProfile as caller identity and require
node:<StableID>. Their names and tags remain attributes. Evidence has
local_daemon assurance.
Native platform gaps are explicit: this release does not discover either
macOS GUI same-user-proof variant and does not connect to the Windows Tailscale
named pipe. On macOS, pass the discovered loopback endpoint and password,
or use a Unix-socket tailscaled installation. On Windows, pass an explicit
loopback HTTP endpoint. No subprocess-based discovery fallback is attempted.
SPIFFE behind L7 proxies¶
All profiles produce stable workload principals only for exactly one canonical SPIFFE URI in an allowed trust domain:
nginx_spiffe_providerrequires URL-escapedX-SSL-Client-Certand exactX-SSL-Client-Verify: SUCCESSafter nginx verifies the client chain.aws_alb_spiffe_provideracceptsX-Amzn-Mtls-Clientcert-Leafonly under the operator guarantee that the adjacent ALB listener is in mTLS verify mode. Passthrough mode is outside this trust contract.gcp_load_balancer_spiffe_providerrequires the custom variables for certificate-present, chain-verified, SPIFFE ID, and an empty error value.azure_application_gateway_spiffe_providerrequires strict-mode rewrite headers for the client certificate and exact verificationSUCCESS.envoy_xfcc_spiffe_providerrequires adjacent Envoy mTLS withforward_client_cert_details: SANITIZE_SET. It accepts exactly one text XFCC element, one URI, and one SHA-256 Hash. Forwarded chains, duplicate singleton fields, unknown fields, and malformed percent encoding or quoting fail closed.
Certificate profiles parse exactly one PEM leaf and validate the X.509-SVID profile: current validity, one allowed URI SAN, non-CA basic constraints, critical digital-signature key usage without CA signing bits, and both client and server auth when extended key usage is present. Certificate validation by the adapter does not replace the proxy's chain verification.