0

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?

Jimbo
  • 25,790
  • 15
  • 86
  • 131
  • 1
    If you client is a browser then u have to edit your system root CA to “trust” your self signed cert, same with go client but can do programmatically, it’s not server side problem. – owlwalks Feb 18 '20 at 13:57
  • @owlwalks There's nothing I can do about that? I thought that I could append a cert to an already trusted cert and my browser would assume it's trusted. Is my understanding completely off? – Jimbo Feb 18 '20 at 13:58
  • 1
    No I don’t think it’s possible, Youcan also use https://github.com/FiloSottile/mkcert to automate it – owlwalks Feb 18 '20 at 14:01
  • 1
    @Jimbo Have a look at [this](http://www.inanzzz.com/index.php/post/9ats/http2-and-tls-client-and-server-example-with-golang) if it helps one way or another. Nothing to do with Autocert though. Just a simple HTTPS example with Self Signed certs that don't need verification. Right in the middle it mentions similar errors as you are getting. – BentCoder Feb 18 '20 at 14:06
  • 1
    "what do I need to change in my code" - nothing. Your browser doesn't trust self-signed certificates, as well it shouldn't. You must add the certificate to the machine's trusted certificate store if you want the machine to trust it. If there was any way around this in the server code, the entirety of internet security wouldn't work. – Adrian Feb 18 '20 at 14:34
  • Many thanks for your input all, and for helping me understand what is happening / why. I think mkcert looks like what I need - it'll register a cert authority locally, and then uses that to generate a cert locally trusted localhost. I can run those commands programatically with Go. I'll get a PoC working and then answer this post with links to your help. Cheers! – Jimbo Feb 18 '20 at 18:02

0 Answers0