使用Golang调用Ansible Tower API遇x509证书错误求助
Hey there! Let's work through this certificate error you're hitting when calling the Ansible Tower API from your Go code. First, let's break down what's happening:
Get "https://ansibletower.micron.com/api/v2/hosts/": x509: certificate relies on legacy Common Name field, use SANs instead
This error pops up because starting with Go 1.15, the standard library requires SSL certificates to use Subject Alternative Names (SANs) instead of just the Common Name (CN) field for hostname validation. Postman uses more lenient validation by default, which is why it works smoothly there.
Let's go through the possible solutions, ordered from quick test fixes to production-ready approaches:
1. Quick fix: Skip certificate validation (test environments only)
If you're just testing and don't need strict certificate checks, you can configure your HTTP client to skip verifying the certificate. Never use this in production—it leaves you open to man-in-the-middle attacks.
Modify your http.Client setup like this:
client := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, }, }
Your updated GetAnsibleHosts function would look like:
package globals import ( "fmt" "io/ioutil" "net/http" "crypto/tls" ) func GetAnsibleHosts() (string, error) { url := "https://zzzztower.zzzz.com/api/v2/hosts/" method := "GET" // Configure client to skip certificate validation (test only!) client := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, }, } req, err := http.NewRequest(method, url, nil) if err != nil { return "", fmt.Errorf("Error creating request: %v", err) } bearerToken := "aaaaaaaaaaaaaaaaaaaaaaaaaaa" req.Header.Add("Authorization", "Bearer "+bearerToken) res, err := client.Do(req) if err != nil { fmt.Println(err) return "", err } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println(err) return "", err } return string(body), err }
2. Production-ready fix: Use a custom certificate pool
If the Ansible Tower server uses an internal CA-signed certificate, you can add that CA certificate to Go's trusted pool so it validates correctly.
Steps:
- Save your internal CA certificate as a file (e.g.,
ca.crt) - Load the certificate into a
x509.CertPool - Configure the HTTP client to use this pool for validation
Here's how to implement this:
package globals import ( "fmt" "io/ioutil" "net/http" "crypto/tls" "crypto/x509" ) func GetAnsibleHosts() (string, error) { url := "https://zzzztower.zzzz.com/api/v2/hosts/" method := "GET" // Load CA certificate caCert, err := ioutil.ReadFile("ca.crt") if err != nil { return "", fmt.Errorf("Error reading CA cert: %v", err) } // Create cert pool and add CA cert certPool := x509.NewCertPool() if !certPool.AppendCertsFromPEM(caCert) { return "", fmt.Errorf("Failed to add CA cert to pool") } // Configure client with custom cert pool client := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ RootCAs: certPool, }, }, } req, err := http.NewRequest(method, url, nil) if err != nil { return "", fmt.Errorf("Error creating request: %v", err) } bearerToken := "aaaaaaaaaaaaaaaaaaaaaaaaaaa" req.Header.Add("Authorization", "Bearer "+bearerToken) res, err := client.Do(req) if err != nil { fmt.Println(err) return "", err } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println(err) return "", err } return string(body), err }
3. Fixing the GODEBUG environment variable
You mentioned trying GODEBUG=x509ignoreCN=0 but it didn't work—that's because you used the wrong value! The x509ignoreCN flag:
0(default in Go 1.15+): Require SANs, reject CN-only certificates1: Allow CN-only certificates (revert to pre-1.15 behavior)
To make this work, set the environment variable to x509ignoreCN=1 before running your Go program:
# Linux/macOS export GODEBUG=x509ignoreCN=1 ./your-go-program # Windows (PowerShell) $env:GODEBUG="x509ignoreCN=1" .\your-go-program.exe
This is a quick workaround, but like skipping validation, it's not ideal for production since it weakens certificate security. The best long-term fix is to update the Ansible Tower server's certificate to include SANs matching the hostname.
内容的提问来源于stack exchange,提问作者SRM KTR

