Failed to connect to a server with Golang due x509 certificate relies on legacy Common Name field
Asked Answered
D

1

8

I'm trying to connect on a mongodb server, to connect I have to provide a CA cert file and also tls cert file.

When I use the following command I don't have issue

$ mongo --host customhost:port DB --authenticationDatabase=DB -u ACCOUNT -p PWD --tls --tlsCAFile /etc/ca-files/new-mongo.ca.crt --tlsCertificateKeyFile /etc/ca-files/new-mongo-client.pem 

But when I try to connect with mongo (and also tested with just a tls client) I have the following error:

failed to connect: x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0

If I use the env variable everything works well but I would like to know how to fix it without having to use it.

const CONFIG_DB_CA = "/etc/ca-files/new-mongo.ca.crt"

func main() {
    cer, err := tls.LoadX509KeyPair("mongo-server.crt", "mongo-server.key")
    if err != nil {
        log.Println(err)
        return
    }

    roots := x509.NewCertPool()
    ca, err := ioutil.ReadFile(CONFIG_DB_CA)
    if err != nil {
        fmt.Printf("Failed to read or open CA File: %s.\n", CONFIG_DB_CA)
        return
    }
    roots.AppendCertsFromPEM(ca)

    tlsConfig := &tls.Config{
        Certificates: []tls.Certificate{cer},
        RootCAs:      roots,
    }

    conn, err := tls.Dial("tcp", "customhost:port", tlsConfig)
    if err != nil {
        fmt.Printf("failed to connect: %v.\n", err)
        return
    }

    err = conn.VerifyHostname("customhost")
    if err != nil {
        panic("Hostname doesn't match with certificate: " + err.Error())
    }
    for i, cert := range conn.ConnectionState().PeerCertificates {
        prefix := fmt.Sprintf("CERT%d::", i+1)
        fmt.Printf("%sIssuer: %s\n", prefix, cert.Issuer)
        fmt.Printf("%sExpiry: %v\n", prefix, cert.NotAfter.Format(time.RFC850))
        fmt.Printf("%sDNSNames: %v\n\n", prefix, cert.DNSNames)
    }
    
    fmt.Printf("Success!")
}

Certificates:

$ openssl x509 -in /etc/ca-files/new-mongo.ca.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            ....
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = FR, ST = IDF, L = Paris, O = COMP, OU = IT, CN = newmongo
        Validity
            Not Before: Jun 30 13:02:12 2021 GMT
            Not After : Jun 30 13:02:12 2023 GMT
        Subject: C = FR, ST = IDF, L = Paris, O = COMP, OU = IT, CN = newmongo

...

        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                ...
            X509v3 Authority Key Identifier: 
                ....

            X509v3 Basic Constraints: critical
                CA:TRUE
$ openssl x509 -in /etc/ca-files/newmongo-client.pem -text -noout 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            ...
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = FR, ST = IDF, L = Paris, O = COMP, OU = IT, CN = newmongo
        Validity
            Not Before: Jun 30 13:17:25 2021 GMT
            Not After : Jun 30 13:17:25 2023 GMT
        Subject: C = FR, ST = IDF, L = Paris, O = COMP, OU = IT, CN = newmongo-client
...
        X509v3 extensions:
            X509v3 Subject Alternative Name: 
                DNS:customhost:port, DNS:customhost, DNS:newmongo-client

I'm a bit stuck and don't know if the problem is my code configuration of tls and the way I loaded certificates or if it comes from the SSL certificate misconfiguration but from what certificates look fine. I feel like loaded certificate are ignored for any reason.

Durstin answered 30/6, 2021 at 14:15 Comment(5)
Have you tried doing as the error message suggests and using a certificate with SANs?Jabin
@Jabin I think there SAN in the last code block i printed the certificate and we can see the "SAN" : X509v3 Subject Alternative Name: DNS:customhost:port, DNS:customhost, DNS:newmongo-client Or maybe I misunderstood what SAN wasDurstin
is the openssl output above your full X509v3 extensions section? Do you have a X509v3 Basic Constraints: CA:FALSE ?Gertrude
Also I think the warning is against your server cert mongo-server.crt not your client cert - so can you post an openssl query of that cert.Gertrude
Short and nice answer here https://mcmap.net/q/348238/-how-do-i-use-sans-with-openssl-instead-of-common-nameNim
G
9

You need to fix the problem at the source and generate a certificate with a DNS SAN field - then the Go runtime check will disappear.

This is achievable with openssl but is tricky as it requires a config file - as SAN field options are too broad to fit into simple command-line options.

The general gist is, create a CSR:

openssl req -new \
    -subj "${SUBJ_PREFIX}/CN=${DNS}/emailAddress=${EMAIL}" \
            -key "${KEY}" \
    -addext "subjectAltName = DNS:${DNS}" \
    -out "${CSR}"

and then sign the CSR with your root CA:

openssl ca \
        -create_serial \
                -cert "${ROOT_CRT}" \
        -keyfile "${ROOT_KEY}" \
                -days "${CERT_LIFETIME}" \
                -in "${CSR}" \
        -batch \
        -config "${CA_CONF}" \
                -out "${CRT}"

CA_CONF referenced above looks something like this:

[ ca ]
default_ca      = my_ca

[ my_ca ]
dir             = ./db
database            = $dir/index.txt
serial              = $dir/serial
new_certs_dir   = $dir/tmp
x509_extensions = my_cert
name_opt            = ca_default
cert_opt            = ca_default
default_md          = default
policy              = policy_match
# 'copy_extensions' will copy over SAN ("X509v3 Subject Alternative Name") from CSR
copy_extensions = copy

[ my_cert ]
basicConstraints        = CA:FALSE
nsComment               = "generated by https://github.com/me/my-pki"
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid,issuer

[ policy_match ]
# ensure CSR fields match that of delivered Cert
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

Inspecting the resulting server cert:

openssl x509 -in server.crt -noout -text

should then have a SAN section like:

X509v3 Subject Alternative Name: 
    DNS:myserver.com
Gertrude answered 30/6, 2021 at 14:37 Comment(2)
We finally fixed it, as you said the root cause was related to servert crt and not the client one. The mongo server certificat setup was not configured correctly with SANs after regenerating it correctly everything started to work better ! ThanksDurstin
a lot of unclear parts in this answer, this seems much more useful: https://mcmap.net/q/348238/-how-do-i-use-sans-with-openssl-instead-of-common-name (of #64814673)Newmann

© 2022 - 2024 — McMap. All rights reserved.