6

I develop a NewRequestWithCert function that create new soap.client and use cert from cert file and after soap.client.Do it returned x509: cannot validate certificate for because it doesn't contain any IP SANs. What wrong with my code ?

func (o *Client) NewRequestWithCert(urlLink string, requestData interface{}, responseData interface{}, certName string, host string) error {
    // Keep on client
    o.requestData = &requestData
    o.responseData = &responseData
    o.url = urlLink

    certByte, errCert := ioutil.ReadFile("/app/certificates/" + certName)
    if errCert != nil {
        logrus.Errorf("cert err: %v", errCert)
        return errCert
    }
    caCertPool := x509.NewCertPool()
    caCertPool.AppendCertsFromPEM(certByte)
    logrus.Debug("certByte : ", certByte)

    tlsConfig := &tls.Config{
        ServerName: host,
        ClientCAs:  caCertPool,
        ClientAuth: tls.RequireAndVerifyClientCert,
    }
    // New http client
    o.client = &http.Client{
        Timeout:   30 * time.Second,
        Transport: &http.Transport{
            TLSClientConfig: tlsConfig,
        },
    }

    // Make buffer
    var requestDataBuffer bytes.Buffer
    err := xml.NewEncoder(&requestDataBuffer).Encode(requestData)

    logrus.Info("[ProxyRequest] URL: ", urlLink)
    logrus.Info("[ProxyRequest] Data: ", requestDataBuffer.String())

    // Build a new request, but not doing the POST yet
    req, err := http.NewRequest("POST", urlLink, &requestDataBuffer)
    if err != nil {
        return err
    }

    // Keep on client
    o.req = req

    // Fill default header
    o.fillHeader()

    return nil
}
LuneLun
  • 61
  • 1
  • 2
  • The problem does not lie within your code. The issue is with the certificate file you are using. See how to [generate a CSR & sign it with custom SAN fields](https://stackoverflow.com/questions/68196502/failed-to-connect-to-a-server-with-golang-due-x509-certificate-relies-on-legacy/68196866#68196866) – colm.anseo Sep 28 '22 at 12:46

2 Answers2

2

The subject(s) of the servers certificate do not match the URL you use in your code. Specifically you likely used an IP address for the URL and the server certificate does not contain a Subject Alternative Names extension (SAN) for this IP address (or any other IP address, hence "doesn't contain any IP SANs")

The cause of this mismatch is that you are using a wrong URL or that the server certificate is wrong.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Since I encountered a specific case in which this happens, it's worth noting that it could also be that the certificate is by hostname and you might be trying to use it by IP address. – Yoav Feuerstein Aug 03 '23 at 11:20
0

In my case the certificates were provided to me and worked fine with the myslq (MariaDB) command line client. I was even able to create JKS keystores from them to successfully connect through JDBC. However, my golang code threw this error. My googling led me to https://github.com/prometheus/prometheus/issues/1654#issuecomment-462433443 which gave me a workaround - setting InsecureSkipVerify to true (to skip verification of certificate). Refer to https://godoc.org/crypto/tls#Config for example usage.

alwayslearning
  • 101
  • 1
  • 1