I'm writing a config daemon.
It works like this:
accepts
methods
example:
PUT http://server1/key
(body = value)
stores value under key
GET http://server1/key
returns value in response body
Now, when a PUT, POST, DELETE is made it duplicates this request and sends it to peers, so that every node has the same data and any node can be queried in case one of the nodes is unavailable. It adds a header so the nodes know that they shouldn't duplicate a request and send out to other nodes.
Ok, this works so far, but now I'd like to only allow the nodes and a WebUI to be able to transmit requests to those nodes. And here is where TLS comes into play.
As far as I understand I need a rootCA, so I can sign server and client certificates. And I'd like to have valid certificates, not "self-signed" because I would use Go and crypto/tls and it should verify the certificates.
My question is:
Which extensions or fields do each of the certificates need? I wouldn't want to re-generate the server and client certs when a new node is added to the config server pool.
I would connect by IP address, not by hostname/dnsname (to skip hostname lookups and the potential eavesdropping of a third party by assigning an IP to their own dnsname, e.g. s1.myserver.com is mine with IP 1.2.3.4 and random dude creates a DNS entry with random.dude.com 1.2.3.4, because I get a list of all nodes by doing a NS lookup of clustercfg.mydomain.com)
On each new node I'd need to create a server cert (this is me, verify that it's true)
On each new node I'd need to create a client cert (so I can authenticate that this client node is valid and is allowed to access this server node)
The question is:
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment, Certificate Sign
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Alternative Name:
DNS:server1.myserver.com, IP Address:2a02::0:0:0:0:0:0:2, IP Address:1.2.3.4
What does a rootCA, a server certificate, a client certificate need so I'm able to do "TLS Authentication"?
You can use a normal server certificate like the ones you use in a web server for the server. Go will check that properly when you connect.
As for client certificates, here is a gist showing how to generate and use the client certificates from Go.
I've uses this code for a similar secure system of clients contacting servers.
You don't need to connect by IP address as the client will check the server's certificate matches the hostname which is an extremely good check.
Hope that helps!
What is needed?
2 and 3 are optional
CAs need template.KeyUsage = x509.KeyUsageCertSign | x509.KeyUsageCRLSign
Sign the certificate with the least CA created. The least CA will be the one you will use to verify client certificates
This certificate also acts as a client certificate, so it needs
template.KeyUsage = x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}
If you need more security add SANs.
template.DNSNames
template.IPAddresses
a
var (
selfname string
certFile = flag.String("cert", "", "server certificate file.")
keyFile = flag.String("key", "", "server private key file.")
rootCA = flag.String("ca", "cacerts.pem", "rootca")
)
certpool := x509.NewCertPool()
pem, err := ioutil.ReadFile(*rootCA)
if err != nil {
log.Fatalf("Failed to read client certificate authority: %v", err)
}
if !certpool.AppendCertsFromPEM(pem) {
log.Fatalf("Can't parse client certificate authority")
}
config := &tls.Config{
ServerName: selfname, // os.Hostname()
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: certpool,
MinVersion: tls.VersionTLS10,
}
server := http.Server{
Addr: ":12345",
ReadTimeout: time.Second * 10,
WriteTimeout: time.Second * 10,
TLSConfig: config,
}
log.Fatalln(server.ListenAndServeTLS(*certFile, *keyFile))