Using Autocert in Go and appending a self-signed certificate to serve https locally

788 Views Asked by At

My goal is to serve a simple https endpoint both locally and in production. I found the autocert package which I believe I can use in production with lets encrypt. I found gssc to start a https server locally with self-signed certs. Finally, How to trust extra CA certs in your Go App looks useful. I have taken ideas from all these sources and tried to use them together, although I'm not sure all of them are needed.

My understanding is that I can use AppendCertsFromPEM to append a self-signed certificate to another certificate and this will enable clients to stop complaining when trying to load locally. Also apparently with autocert I don't even need to generate certificate files myself on my local machine.

When I visit https://localhost:443 I still get the following error:

2020/02/18 14:38:42 http: TLS handshake error from [::1]:51832: EOF

In order to append a self-signed certificate, I downloaded one publicly available from here and then append mine onto this. Is this the correct approach or do I need another one from somewhere else (I can't find one on my local system).

Here is my code:

// Router.
r := mux.NewRouter()
r.HandleFunc("/", Handler)

// Autocert.
m := &autocert.Manager{
    Prompt:     autocert.AcceptTOS,
    HostPolicy: autocert.HostWhitelist("localhost"), // Will change when I go to prod
    Cache:      autocert.DirCache("."), // Where certs are stored
}

// Default server config.
server := &http.Server{
    Handler:   r,
    Addr:      ":https",
    TLSConfig: &tls.Config{GetCertificate: m.GetCertificate}, // Default for prod.
}

// If dev, overwrite TLSConfig with new values (appended cert). 
if os.Getenv("APP_ENV") == "dev" {
    // Get the SystemCertPool, continue with an empty pool on error
    rootCAs := x509.NewCertPool()
    certs, _ := ioutil.ReadFile("./cert_downloaded_from_mozilla.crt")
    _ = rootCAs.AppendCertsFromPEM(certs)

    xsert := gssc.GetCertificate("localhost")

    server.TLSConfig = &tls.Config{
        InsecureSkipVerify: true,
        RootCAs:            rootCAs,
        ServerName:         "localhost",
        GetCertificate:     xsert,
    }

    server.TLSConfig.BuildNameToCertificate() // Do I even need to call this?
}

panic(server.ListenAndServeTLS("", ""))

I've read that I don't need to provide anything to server.ListenAndServeTLS because we're using autocert, but then I had an error as it wasn't able to open the file.

Basically, without DNS changes etc, am I actually able to serve something from localhost using an appended certificate without the "This connection is not private" warning in my local browser and what do I need to change in my code to achieve this if it is possible?

0

There are 0 best solutions below