Certificate check from Go

As the web moves more and more to HTTPS and ehanced security (such as HSTS) keeping your certificates updated and valid becomes more and more important.

I’m toying with an idea of building a small webapp to monitor my small portfolio of certificates and warn me if a certificate is due to expire. As part of this, I’m slowly patching pieces together in Go and one of the small useful outcomes is a small (compilable to bin) script which prints the basic certificate details of a given domain.

package main

import (
    "bytes"
    "crypto/tls"
    "crypto/x509" // https://golang.org/pkg/crypto/x509/
    "encoding/pem"
    "fmt"
    "os"
)

func GetCertificatesPEM(address string) (string, error) {
    conn, err := tls.Dial("tcp", address, &tls.Config{
        InsecureSkipVerify: true,
    })
    if err != nil {
        return "", err
    }
    defer conn.Close()
    var b bytes.Buffer
    for _, cert := range conn.ConnectionState().PeerCertificates {
        err := pem.Encode(&b, &pem.Block{
            Type: "CERTIFICATE",
            Bytes: cert.Raw,
        })
        if err != nil {
            return "", err
        }
    }
    return b.String(), nil
}

func main() {
    domainArg := os.Args[1]

    certs, err := GetCertificatesPEM(domainArg + ":443")
    if err != nil {
        fmt.Print("err %v\n", err.Error())
    }

    block, _ := pem.Decode([]byte(certs))
    cert, err := x509.ParseCertificate(block.Bytes)
    if err != nil {
        panic("failed to parse certificate: " + err.Error())
    }

//fmt.Printf("len %v : %v\n", len(certs), certs)
fmt.Println(cert.Subject)
fmt.Println(cert.Issuer)
fmt.Println(cert.NotAfter)

Script Output

Once run the output could look something like this:

$ go run checkCertificate.go netfactory.dk
CN=netfactory.dk
CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US
2020-08-12 04:47:13 +0000 UTC

You can (also) find the above source code in my GoLang snippets Library on Github.