Example: HTTP Client Trust a Custom CA
Go's HTTP client trusts certificates signed by the system's trusted CAs by default.
If an HTTPS server uses a private CA, the client will reject its certificate unless that CA is trusted.
Add the private CA to the client's RootCAs instead of disabling certificate verification.
Quick Example
Load the private CA certificate, add it to the system certificate pool, and use the pool in tls.Config:
The important part is:
RootCAs tells the TLS client which root CAs it can trust when verifying the server certificate.
Keep the System CAs
If the client needs to connect to both public and private HTTPS services, start with SystemCertPool:
Don't start with an empty pool:
NewCertPool contains no certificates initially. Using it means the client trusts only the certificates you explicitly add.
That can be correct for a client that intentionally trusts only a private CA. It is usually not what you want for an application that also calls normal public HTTPS services.
Don't Use InsecureSkipVerify
A private CA does not require disabling certificate verification.
Avoid:
This disables normal server certificate verification.
If you get:
check whether the private root CA is missing from the trust pool.
Also check the server's certificate chain. An incomplete chain, such as a missing intermediate certificate, can produce the same error.
Use ServerName When the Connection Address Doesn't Match
The TLS name being verified does not have to be the same as the address used to establish the TCP connection.
For example, a service might be reached through:
while its certificate is issued for:
Set ServerName when the certificate name needs to be different from the connection address:
ServerName controls the name used for certificate verification. It does not change the destination address used by the HTTP client.
If the certificate contains the IP address in its SAN, an IP-based URL can be verified directly. Otherwise, the name being verified must match a DNS SAN in the certificate.
Load a CA Bundle Carefully
AppendCertsFromPEM can parse multiple PEM-encoded certificates:
A CA bundle can therefore contain multiple certificates that the application intentionally trusts.
That does not mean every certificate in a server's TLS chain belongs in RootCAs.
Normally, the server sends its intermediate certificates during the TLS handshake, while the client trusts the appropriate root CA. Adding an intermediate certificate to the trust pool changes what the client treats as a trust anchor and should be done deliberately.
Custom CA Is Not Client Authentication
Trusting a private CA only changes how the client verifies the server.
Client authentication is a separate configuration:
RootCAs is for trusting server certificates.
Certificates provides client certificates when the server requests client authentication.
So a private CA does not automatically mean the connection uses mutual TLS.
Reuse the Client
Create the http.Client and http.Transport once and reuse them:
Don't create a new transport for every request.
http.Transport maintains connection state and can reuse connections. http.Client and http.Transport are safe for concurrent use.
If different services require different trust policies, use separate clients or transports rather than changing a shared tls.Config between requests.
Certificate Revocation
Adding a CA to RootCAs establishes trust in certificates issued by that CA. It does not provide general certificate revocation checking.
Go's standard crypto/x509 verification does not automatically perform CRL or OCSP revocation checking.
If certificate revocation is required by your environment, handle it separately according to the service's security requirements.
When to Use This
Use a custom CA when an HTTPS server uses a private or internal certificate authority:
- internal APIs
- private service-to-service HTTPS
- corporate PKI
- development or test environments with their own CA
Keep normal certificate and hostname verification enabled.
The usual solution to:
is to configure the correct trust chain—not to turn TLS verification off.