I am trying to use this certificate with a connection between an InfluxDB rest endpoint that is behind an nginx reverse-proxy and my simple client written in GoLang.
I started using SSL Certificates generated with openssl using the tutorial found at this link which runs me through creating and self-singing a certificate.
But I get this error every time I try to make this connection:
x509: certificate signed by unknown authority (possibly because of "x509: invalid signature: parent certificate cannot sign this kind of certificate" while trying to verify candidate authority certificate "<My Certificate Name>")
I have yet to find a way to get this resolved, but I'll show what I can see as relevant:
As far as I can tell, the nginx rules for InfluxDB were fairly easy to write and ended up looking like this:
# InfluxDB
server {
ssl on;
ssl_protocols TLSV1.2 TLSV1.1 TLSV1;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
listen 8086;
access_log /var/log/nginx/influxdb.access.log;
error_log /var/log/nginx/influxdb.error.log;
location / {
include /etc/nginx/conf.d/options.conf.inc;
include /etc/nginx/conf.d/auth.conf.inc;
proxy_pass http://127.0.0.1:8087;
}
}
Where options.conf.inc is:
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin $served_at;
add_header Access-Control-Allow-Methods "GET, OPTIONS";
add_header Access-Control-Allow-Headers "Authorization";
add_header Access-Control-Allow-Credentials "true";
add_header Content-Length 0;
add_header Content-Type text/plain;
return 200;
}
Where the auto.conf.inc is:
add_header Access-Control-Allow-Headers "Authorization";
add_header Access-Control-Allow-Credentials "true";
auth_basic "Restricted";
auth_basic_user_file <pathTo>.htpasswd;
error_page 401 /401.html;
My golang client looks like this:
func main() {
flag.Parse()
// Load client cert
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
log.Fatal(err)
}
// Load CA cert
caCert, err := ioutil.ReadFile(caFile)
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// Setup HTTPS client
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: caCertPool,
// InsecureSkipVerify: true,
}
//tlsConfig.BuildNameToCertificate()
transport := &http.Transport{TLSClientConfig: tlsConfig}
client := &http.Client{Transport: transport}
// Do GET something
resp, err := client.Get("https://fillerBasicAuthCredentials:password!1@192.168.223.128:8086/query?q=show+databases")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// Dump response
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
log.Println(string(data))
}
As you can see in my golang code, is that I have played with the InsecureSkipVerify
flag on the tlsConfig object. Setting this to true makes everything work, but seems inherently bad to do since it defeats a lot of the point of using the cert in the first place.
The options I have left, it seems, is to generate a CA cert and use THAT to sign my regular cert, but that also seems like more of a hack than I should be needing to do.
EDIT (Solution):
After exploring creating my own CA cert to sign these with I was able to get everything working. Now I have a CA cert that I will use to sign my other certs, and I will be installing this CA cert on the boxes so they know it is a trusted cert.
Pieces that were helpful in how I solved this:
I am using an open source influxdb client that I was trying to avoid using. It currently uses golang's net/http
package, and not the crypto
which means I can't specify my CA certs in-code like my example does. I had to install the CA cert onto my box so it was recognized properly. An article I found helpful on this topic is [this one]https://www.happyassassin.net/2015/01/14/trusting-additional-cas-in-fedora-rhel-centos-dont-append-to-etcpkitlscertsca-bundle-crt-or-etcpkitlscert-pem/
That error message is coming from go's CheckSignatureFrom method. It looks like it requires the CA flag in basicConstraints
to be set to true, and if the keyUsage
field is present (it is in the example you linked but it's not in most instructions I've seen for using self-signed certs) it must include the keyCertSign
value.
When I've faced similar problems I've created a CA that is separate from the server certificate. It's a little more work, but it's not a "hack"; if anything setting up the self-signed cert to be properly recognized as its own CA is the hackier solution.