in a project I need to program in Go code to connect a https site which is deployed with a self-signed TLS certs; I am provided the server certs files: (the ca.cert
ca.key
, client.cert
client.key
client.csr
and server configured with server.cert
server.key
server.csr
);
I have figured out the following code indeed works
cert, err := tls.LoadX509KeyPair("./client.crt", "./client.key")
// if err != nil { ... }
rootCAs := x509.NewCertPool()
certs, err := ioutil.ReadFile("./ca.crt")
// if err != nil { ... }
// Append our cert to the system pool
if ok := rootCAs.AppendCertsFromPEM(certs); !ok { ... }
config := tls.Config{
Certificates: []tls.Certificate{cert},
InsecureSkipVerify: true,
ServerName: "ingress.local",
RootCAs: rootCAs,
}
conn, err := tls.Dial("tcp", "some-site.xyz:443", &config)
if err != nil {
if x509err, ok := err.(x509.UnknownAuthorityError); ok {
fmt.Printf("unknown rootCert: %#v
", x509err.Cert)
}
log.Fatalf("client: dial: %#v
\t%+v", err, err)
}
tr := &http.Transport{TLSClientConfig: &config}
client := &http.Client{Transport: tr}
// Uses local self-signed cert
req, err := http.NewRequest(http.MethodGet, "https://some-site.xyz", nil)
if err != nil {
log.Fatalf("client: http new request: %#v", err, err)
}
now the question is: if I don't set the InsecureSkipVerify: true
in tls.Config, the code failed with errors:
1. if not set ServerName
correctly, it's x509.HostnameError
this service is running with a k8s ingress, and I figured out the correct hostname is ingress.local
2. even if I set ServerName
correctly, it now failed with x509.UnknownAuthorityError
The other way I've tried is to not loading ca.cert
at all, only 1 line of InsecureSkipVerify: true
can make all of this working, and only required files are the client.cert
client.key
if I set only the InsecureSkipVerify: true
without loading the client certs, that results an 400 Bad Request No required SSL certificate was sent
proved that server side is configured with requiring the client certs;
cert, err := tls.LoadX509KeyPair("./client.crt", "./client.key")
config := tls.Config{
Certificates: []tls.Certificate{cert},
InsecureSkipVerify: true,
}
// same tls.Dial or http.NewRequest works well ...
I want to try the best effort to avoid setting InsecureSkipVerify: true
wonder is there any way possible to make it working without InsecureSkipVerify: true
? Is the way above of loading ca.cert
into a CertPool has anything wrong? the provided files include ca.key
and *.csr
files as well, but from all online existing TLS connection go code samples I don't see where can they be useful ?
If there's no way to make it working without InsecureSkipVerify: true
, then is it still meaningful to load the ca.cert
?
Update one more thing: I've tried with curl --cacert ./ca.crt --cert ./client.crt --key client.key https://some-site.xyz -k
got same with above Go code, that is together with -k
(--insecure
) it works, with cacert or without; but without -k
it got similar errors:
* successfully set certificate verify locations:
* CAfile: ./ca.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0