I am looking to connect a server and a number of clients using mTLS in golang. On my server I would like to be able to generate certificates to put on all the clients so clients can talk to the server but clients cannot talk to each other. My clients however, expose the golang http server on port 80 and my server communicates with the clients through API requests rather than the other way around (technically you could question whether what I am calling a server is in fact a client, but it’s a single source for certificate generation and serves content to the clients so will stick with this naming for simplicity). How could this be set up? Which certificates would need to be generated and is it possible to have the clients listen for requests using certificates generated from a single server?
I will most likely be using SmallStep for certificate generation and SmallStep examples would be useful, but the general approach would be fine too and can then look at how to replicate it with SmallStep separately.
I have looked at some existing golang examples but they tend to be steered at different setups:
https://smallstep.com/hello-mtls/doc/server/go
https://venilnoronha.io/a-step-by-step-guide-to-mtls-in-go
Here is the code at the moment which I am quite sure is using the certificates incorrectly :
Client:
step ca certificate "localhost" client.crt client.key
In the below, cert and key variables are client.crt and client.key respectively.
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM([]byte(cert))
// Read the key pair to create certificate
keyPair, err := tls.X509KeyPair([]byte(cert), []byte(key))
if err != nil {
log.Fatal(err)
}
transport = &http.Transport{
IdleConnTimeout: transportIdleConnTimeout,
MaxIdleConnsPerHost: transportMaxIdleConnsPerHost,
TLSClientConfig: &tls.Config{
RootCAs: caCertPool,
Certificates: []tls.Certificate{keyPair},
},
Server:
step ca certificate "pm1" server.crt server.key
In the below, cert and key variables are server.crt and server.key respectively.
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM([]byte(cert))
cert, err := tls.X509KeyPair([]byte(cert), []byte(key))
if err != nil {
log.Fatal("server: loadkeys: ", err)
}
tlsConfig := tls.Config{
ClientCAs: caCertPool,
ClientAuth: tls.RequireAndVerifyClientCert,
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS13,
}
I am not using ca.crt (step ca root ca.crt
) at all right now.