ASVS 5.0 V12.3.4 requires internal TLS connections to use trusted certificates. If you issue your own certificates or use self signed ones, each consuming service must trust only the specific internal CAs or specific self signed certificates it needs, not everything. It is Level 2.
Why it matters
The shortcut is to add the internal CA to the system trust store, or worse, disable checks. Adding a private CA to the global store means that CA can now vouch for any hostname, including public ones. If that CA key leaks, or if one team's CA is sloppy, every service that trusts it is exposed.
Scoping trust limits the blast radius to the connections that actually need it.
How to implement it
Give each client its own CA bundle for each upstream, containing only the issuer for that upstream.
Go:
pool := x509.NewCertPool()
pem, err := os.ReadFile("/etc/pki/orders-ca.pem")
if err != nil { log.Fatal(err) }
pool.AppendCertsFromPEM(pem)
client := &http.Client{
Timeout: 5 * time.Second,
Transport: &http.Transport{TLSClientConfig: &tls.Config{RootCAs: pool, MinVersion: tls.VersionTLS12}},
}
Note that setting RootCAs replaces the system pool for that client, which is the intent here.
Other practices: use an internal CA with name constraints so it can only sign your internal domains, keep its key offline or in an HSM, issue short lived leaf certificates, and never copy a self signed leaf into a global store.
How to test it
Present the client with a certificate signed by a different internal CA that is valid for the right hostname. The connection must fail. Present a public CA certificate for an internal name (if you can arrange one in a test environment). It must also fail.
openssl s_client -connect orders.internal:8443 -CAfile /etc/pki/other-ca.pem -verify_return_error < /dev/null
Expect a verify error.
Common mistakes
- Baking the internal CA into base images used by every service.
- Using one root for dev, staging and production.
- Long lived self signed certificates with no rotation.
Quick check
Why not trust the internal CA system wide?
Because a compromise or misissue by that CA then affects every connection. Scoped trust limits the damage.