From f8fe382c02f35be55ffb683553052c2c20f04e7d Mon Sep 17 00:00:00 2001 From: "Matthew R. Kasun" Date: Sat, 16 Apr 2022 16:43:10 -0400 Subject: [PATCH] cleanup and comments --- controllers/server.go | 8 +++++--- docker/mosquitto.conf | 4 ++-- netclient/config/config.go | 1 - netclient/functions/daemon.go | 17 +++++------------ netclient/functions/register.go | 27 +++++++++++++-------------- tls/tls.go | 18 +++++++++++++----- 6 files changed, 38 insertions(+), 37 deletions(-) diff --git a/controllers/server.go b/controllers/server.go index f6a8162a..2578dfeb 100644 --- a/controllers/server.go +++ b/controllers/server.go @@ -112,7 +112,7 @@ func getConfig(w http.ResponseWriter, r *http.Request) { // json.NewEncoder(w).Encode("Server added to network " + params["network"]) // } -// register - registers a client with the server and return the CA cert +// register - registers a client with the server and return the CA and cert func register(w http.ResponseWriter, r *http.Request) { logger.Log(2, "processing registration request") w.Header().Set("Content-Type", "application/json") @@ -164,9 +164,7 @@ func register(w http.ResponseWriter, r *http.Request) { returnErrorResponse(w, r, errorResponse) return } - // not working --- use openssl instead cert, ca, err := genCerts(&request.Key, &request.CommonName) - //cert, ca, err := genOpenSSLCerts(&request.Key, &request.CommonName) if err != nil { logger.Log(0, "failed to generater certs ", err.Error()) errorResponse := models.ErrorResponse{ @@ -178,6 +176,8 @@ func register(w http.ResponseWriter, r *http.Request) { tls.SaveCert("/tmp/sent/", "root.pem", ca) tls.SaveCert("/tmp/sent/", "client.pem", cert) + //x509.Certificate.PublicKey is an interface therefore json encoding/decoding result in a string value rather than a []byte + //include the actual public key so the certificate can be properly reassembled on the other end. response := config.RegisterResponse{ CA: *ca, CAPubKey: (ca.PublicKey).(ed25519.PublicKey), @@ -188,6 +188,7 @@ func register(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(response) } +// genCerts generates a client certificate and returns the certificate and root CA func genCerts(clientKey *ed25519.PrivateKey, name *pkix.Name) (*x509.Certificate, *x509.Certificate, error) { ca, err := tls.ReadCert("/etc/netmaker/root.pem") if err != nil { @@ -212,6 +213,7 @@ func genCerts(clientKey *ed25519.PrivateKey, name *pkix.Name) (*x509.Certificate return ca, cert, nil } +// genCerts generates a client certificate using calls to openssl and returns the certificate and root CA func genOpenSSLCerts(key *ed25519.PrivateKey, name *pkix.Name) (*x509.Certificate, *x509.Certificate, error) { if err := tls.SaveKey("/tmp/", "client.key", *key); err != nil { return nil, nil, fmt.Errorf("failed to store client key %w", err) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 8b6b4b93..6d1f9c8f 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -9,5 +9,5 @@ require_certificate true use_identity_as_username true cafile /mosquitto/certs/root.pem -certfile /mosquitto/certs/broker.pem -keyfile /mosquitto/certs/broker.key \ No newline at end of file +certfile /mosquitto/certs/server.pem +keyfile /mosquitto/certs/server.key \ No newline at end of file diff --git a/netclient/config/config.go b/netclient/config/config.go index 5ac2bbf9..e880e622 100644 --- a/netclient/config/config.go +++ b/netclient/config/config.go @@ -50,7 +50,6 @@ type RegisterRequest struct { // RegisterResponse - the response to register function type RegisterResponse struct { - Key ed25519.PrivateKey CA x509.Certificate CAPubKey ed25519.PublicKey Cert x509.Certificate diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 83475aef..16d686aa 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -131,7 +131,7 @@ func PingServer(cfg *config.ClientConfig) error { // == Private == // sets MQ client subscriptions for a specific node config -// should be called for each node belonging to a given comms network +// should be called for each node belonging to a given server func setSubscriptions(client mqtt.Client, nodeCfg *config.ClientConfig) { if nodeCfg.DebugOn { if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { @@ -140,7 +140,6 @@ func setSubscriptions(client mqtt.Client, nodeCfg *config.ClientConfig) { } logger.Log(0, "subscribed to all topics for debugging purposes") } - if token := client.Subscribe(fmt.Sprintf("update/%s/%s", nodeCfg.Node.Network, nodeCfg.Node.ID), 0, mqtt.MessageHandler(NodeUpdate)); token.Wait() && token.Error() != nil { logger.Log(0, token.Error().Error()) return @@ -271,7 +270,7 @@ func setupMQTTSub(server string) mqtt.Client { return client } -// NewTLSConf sets up tls to connect to broker +// NewTLSConf sets up tls configuration to connect to broker securely func NewTLSConfig(cfg *config.ClientConfig, server string) *tls.Config { var file string if cfg != nil { @@ -287,18 +286,14 @@ func NewTLSConfig(cfg *config.ClientConfig, server string) *tls.Config { if !ok { logger.Log(0, "failed to append cert") } - //mycert, err := ssl.ReadCert("/etc/netclient/" + server + "/client.pem") clientKeyPair, err := tls.LoadX509KeyPair("/etc/netclient/"+server+"/client.pem", "/etc/netclient/client.key") - //clientKeyPair, err := tls.LoadX509KeyPair("/home/mkasun/tmp/client.pem", "/home/mkasun/tmp/client.key") if err != nil { log.Fatalf("could not read client cert/key %v \n", err) } certs := []tls.Certificate{clientKeyPair} - //certs = append(certs, tls.Certificate(&mycert)) return &tls.Config{ - RootCAs: certpool, - ClientAuth: tls.NoClientCert, - //ClientAuth: tls.VerifyClientCertIfGiven, + RootCAs: certpool, + ClientAuth: tls.NoClientCert, ClientCAs: nil, Certificates: certs, //InsecureSkipVerify: false fails ---- so need to use VerifyConnection @@ -327,7 +322,7 @@ func NewTLSConfig(cfg *config.ClientConfig, server string) *tls.Config { } // setupMQTT creates a connection to broker and return client -// utilizes comms client configs to setup connections +// this function is primarily used to create a connection to publish to the broker func setupMQTT(cfg *config.ClientConfig, publish bool) mqtt.Client { opts := mqtt.NewClientOptions() server := cfg.Server.Server @@ -493,5 +488,3 @@ func read(network, which string) string { } return "" } - -// == End Message Caches == diff --git a/netclient/functions/register.go b/netclient/functions/register.go index 663fd2b8..71267883 100644 --- a/netclient/functions/register.go +++ b/netclient/functions/register.go @@ -24,17 +24,19 @@ func Register(cfg *config.ClientConfig) error { if cfg.Server.AccessKey == "" { return errors.New("no access key provided") } - //create certificate request - _, private, err := ed25519.GenerateKey(rand.Reader) + //generate new key if one doesn' exist + private, err := tls.ReadKey("/etc/netclient/client.key") if err != nil { - return err - } - //csr, err := tls.NewCSR(private, name) - if err != nil { - return err + _, *private, err = ed25519.GenerateKey(rand.Reader) + if err != nil { + return err + } + if err := tls.SaveKey(ncutils.GetNetclientPath(), "client.key", *private); err != nil { + return err + } } data := config.RegisterRequest{ - Key: private, + Key: *private, CommonName: tls.NewCName(os.Getenv("HOSTNAME")), } payload, err := json.Marshal(data) @@ -43,7 +45,6 @@ func Register(cfg *config.ClientConfig) error { } url := "https://" + cfg.Server.API + "/api/server/register" log.Println("register at ", url) - request, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(payload)) if err != nil { return err @@ -62,19 +63,17 @@ func Register(cfg *config.ClientConfig) error { if err := json.NewDecoder(response.Body).Decode(&resp); err != nil { return errors.New("unmarshal cert error " + err.Error()) } - + //x509.Certificate.PublicKey is an interface so json encoding/decoding results in a string rather that []byte + //the pubkeys are included in the response so the values in the certificate can be updated appropriately resp.CA.PublicKey = resp.CAPubKey resp.Cert.PublicKey = resp.CertPubKey - if err := tls.SaveCert(ncutils.GetNetclientPath()+cfg.Server.Server+"/", "root.pem", &resp.CA); err != nil { return err } if err := tls.SaveCert(ncutils.GetNetclientPath()+cfg.Server.Server+"/", "client.pem", &resp.Cert); err != nil { return err } - if err := tls.SaveKey(ncutils.GetNetclientPath(), "client.key", private); err != nil { - return err - } logger.Log(0, "certificates/key saved ") + //join the network defined in the token return JoinNetwork(cfg, "", false) } diff --git a/tls/tls.go b/tls/tls.go index 3d17d1a1..da5bdaac 100644 --- a/tls/tls.go +++ b/tls/tls.go @@ -80,7 +80,7 @@ func ReadFrom(path string) (*Key, error) { return &Key{point}, nil } -// creates a new pkix.Name +// NewName creates a new pkix.Name func NewName(commonName, country, org string) pkix.Name { res := NewCName(commonName) res.Country = []string{country} @@ -88,14 +88,14 @@ func NewName(commonName, country, org string) pkix.Name { return res } -// creates a new pkix.Name with only a common name +// NewCName creates a new pkix.Name with only a common name func NewCName(commonName string) pkix.Name { return pkix.Name{ CommonName: commonName, } } -// creates a new certificate signing request for a +// NewCSR creates a new certificate signing request for a func NewCSR(key ed25519.PrivateKey, name pkix.Name) (*x509.CertificateRequest, error) { dnsnames := []string{} dnsnames = append(dnsnames, name.CommonName) @@ -116,7 +116,7 @@ func NewCSR(key ed25519.PrivateKey, name pkix.Name) (*x509.CertificateRequest, e return csr, nil } -// returns a new self-signed certificate +// SelfSignedCA returns a new self-signed certificate func SelfSignedCA(key ed25519.PrivateKey, req *x509.CertificateRequest, days int) (*x509.Certificate, error) { template := &x509.Certificate{ @@ -145,7 +145,7 @@ func SelfSignedCA(key ed25519.PrivateKey, req *x509.CertificateRequest, days int return result, nil } -// issues a new certificate from a parent certificate authority +// NewEndEntityCert issues a new certificate from a parent certificate authority func NewEndEntityCert(key ed25519.PrivateKey, req *x509.CertificateRequest, parent *x509.Certificate, days int) (*x509.Certificate, error) { template := &x509.Certificate{ Version: req.Version, @@ -170,6 +170,7 @@ func NewEndEntityCert(key ed25519.PrivateKey, req *x509.CertificateRequest, pare return result, nil } +// SaveRequest saves a certificate request to the specified path func SaveRequest(path, name string, csr *x509.CertificateRequest) error { if err := os.MkdirAll(path, 0644); err != nil { return err @@ -187,6 +188,8 @@ func SaveRequest(path, name string, csr *x509.CertificateRequest) error { } return nil } + +// SaveCert save a certificate to the specified path func SaveCert(path, name string, cert *x509.Certificate) error { //certbytes, err := x509.ParseCertificate(cert) if err := os.MkdirAll(path, 0644); err != nil { @@ -206,6 +209,7 @@ func SaveCert(path, name string, cert *x509.Certificate) error { return nil } +// SaveKey save a private key (ed25519) to the specified path func SaveKey(path, name string, key ed25519.PrivateKey) error { //func SaveKey(name string, key *ecdsa.PrivateKey) error { if err := os.MkdirAll(path, 0644); err != nil { @@ -229,6 +233,7 @@ func SaveKey(path, name string, key ed25519.PrivateKey) error { return nil } +// ReadCert reads a certificate from disk func ReadCert(name string) (*x509.Certificate, error) { contents, err := os.ReadFile(name) if err != nil { @@ -245,6 +250,7 @@ func ReadCert(name string) (*x509.Certificate, error) { return cert, nil } +// ReadKey reads a private key (ed25519) from disk func ReadKey(name string) (*ed25519.PrivateKey, error) { bytes, err := os.ReadFile(name) if err != nil { @@ -259,6 +265,7 @@ func ReadKey(name string) (*ed25519.PrivateKey, error) { return &private, nil } +// serialNumber generates a serial number for a certificate func serialNumber() *big.Int { serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) @@ -268,6 +275,7 @@ func serialNumber() *big.Int { return serialNumber } +// duration coverts the number of days to time.duration func duration(days int) time.Duration { hours := days * 24 duration, err := time.ParseDuration(fmt.Sprintf("%dh", hours))