adding functions to handle certs in DB

This commit is contained in:
afeiszli 2022-06-30 21:56:11 -04:00
parent 23fff67bd5
commit b281047168
8 changed files with 120 additions and 29 deletions

View file

@ -142,12 +142,12 @@ func register(w http.ResponseWriter, r *http.Request) {
// 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")
ca, err := tls.ReadCertFromFile("/etc/netmaker/root.pem")
if err != nil {
logger.Log(2, "root ca not found ", err.Error())
return nil, nil, fmt.Errorf("root ca not found %w", err)
}
key, err := tls.ReadKey("/etc/netmaker/root.key")
key, err := tls.ReadKeyFromFile("/etc/netmaker/root.key")
if err != nil {
logger.Log(2, "root key not found ", err.Error())
return nil, nil, fmt.Errorf("root key not found %w", err)

View file

@ -26,6 +26,9 @@ const DELETED_NODES_TABLE_NAME = "deletednodes"
// USERS_TABLE_NAME - users table
const USERS_TABLE_NAME = "users"
// CERTS_TABLE_NAME - certificates table
const CERTS_TABLE_NAME = "certs"
// DNS_TABLE_NAME - dns table
const DNS_TABLE_NAME = "dns"
@ -122,6 +125,7 @@ func InitializeDatabase() error {
func createTables() {
createTable(NETWORKS_TABLE_NAME)
createTable(NODES_TABLE_NAME)
createTable(CERTS_TABLE_NAME)
createTable(DELETED_NODES_TABLE_NAME)
createTable(USERS_TABLE_NAME)
createTable(DNS_TABLE_NAME)

14
main.go
View file

@ -190,21 +190,21 @@ func genCerts() error {
logger.Log(0, "checking keys and certificates")
var private *ed25519.PrivateKey
var err error
private, err = tls.ReadKey(functions.GetNetmakerPath() + "/root.key")
private, err = tls.ReadKeyFromFile(functions.GetNetmakerPath() + "/root.key")
if errors.Is(err, os.ErrNotExist) {
logger.Log(0, "generating new root key")
_, newKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return err
}
if err := tls.SaveKey(functions.GetNetmakerPath(), "/root.key", newKey); err != nil {
if err := tls.SaveKeyToFile(functions.GetNetmakerPath(), "/root.key", newKey); err != nil {
return err
}
private = &newKey
} else if err != nil {
return err
}
ca, err := tls.ReadCert(functions.GetNetmakerPath() + ncutils.GetSeparator() + "root.pem")
ca, err := tls.ReadCertFromFile(functions.GetNetmakerPath() + ncutils.GetSeparator() + "root.pem")
//if cert doesn't exist or will expire within 10 days --- but can't do this as clients won't be able to connect
//if errors.Is(err, os.ErrNotExist) || cert.NotAfter.Before(time.Now().Add(time.Hour*24*10)) {
if errors.Is(err, os.ErrNotExist) {
@ -218,14 +218,14 @@ func genCerts() error {
if err != nil {
return err
}
if err := tls.SaveCert(functions.GetNetmakerPath(), ncutils.GetSeparator()+"root.pem", rootCA); err != nil {
if err := tls.SaveCertToFile(functions.GetNetmakerPath(), ncutils.GetSeparator()+"root.pem", rootCA); err != nil {
return err
}
ca = rootCA
} else if err != nil {
return err
}
cert, err := tls.ReadCert(functions.GetNetmakerPath() + "/server.pem")
cert, err := tls.ReadCertFromFile(functions.GetNetmakerPath() + "/server.pem")
if errors.Is(err, os.ErrNotExist) || cert.NotAfter.Before(time.Now().Add(time.Hour*24*10)) {
//gen new key
logger.Log(0, "generating new server key/certificate")
@ -242,10 +242,10 @@ func genCerts() error {
if err != nil {
return err
}
if err := tls.SaveKey(functions.GetNetmakerPath(), "/server.key", key); err != nil {
if err := tls.SaveKeyToFile(functions.GetNetmakerPath(), "/server.key", key); err != nil {
return err
}
if err := tls.SaveCert(functions.GetNetmakerPath(), "/server.pem", cert); err != nil {
if err := tls.SaveCertToFile(functions.GetNetmakerPath(), "/server.pem", cert); err != nil {
return err
}
} else if err != nil {

View file

@ -94,13 +94,13 @@ func Pull(cfg *config.ClientConfig) error {
}
//generate new client key if one doesn' exist
var private *ed25519.PrivateKey
private, err = tls.ReadKey(ncutils.GetNetclientPath() + ncutils.GetSeparator() + "client.key")
private, err = tls.ReadKeyFromFile(ncutils.GetNetclientPath() + ncutils.GetSeparator() + "client.key")
if err != nil {
_, newKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return err
}
if err := tls.SaveKey(ncutils.GetNetclientPath(), ncutils.GetSeparator()+"client.key", newKey); err != nil {
if err := tls.SaveKeyToFile(ncutils.GetNetclientPath(), ncutils.GetSeparator()+"client.key", newKey); err != nil {
return err
}
private = &newKey

View file

@ -268,7 +268,7 @@ func setupMQTT(cfg *config.ClientConfig, publish bool) (mqtt.Client, error) {
func reRegisterWithServer(cfg *config.ClientConfig) {
logger.Log(0, "connection issue detected.. attempt connection with new certs and broker information")
key, err := ssl.ReadKey(ncutils.GetNetclientPath() + ncutils.GetSeparator() + "client.key")
key, err := ssl.ReadKeyFromFile(ncutils.GetNetclientPath() + ncutils.GetSeparator() + "client.key")
if err != nil {
_, *key, err = ed25519.GenerateKey(rand.Reader)
if err != nil {

View file

@ -151,10 +151,10 @@ func publish(nodeCfg *config.ClientConfig, dest string, msg []byte, qos byte) er
}
func checkCertExpiry(cfg *config.ClientConfig) error {
cert, err := tls.ReadCert(ncutils.GetNetclientServerPath(cfg.Server.Server) + ncutils.GetSeparator() + "client.pem")
cert, err := tls.ReadCertFromFile(ncutils.GetNetclientServerPath(cfg.Server.Server) + ncutils.GetSeparator() + "client.pem")
//if cert doesn't exist or will expire within 10 days
if errors.Is(err, os.ErrNotExist) || cert.NotAfter.Before(time.Now().Add(time.Hour*24*10)) {
key, err := tls.ReadKey(ncutils.GetNetclientPath() + ncutils.GetSeparator() + "client.key")
key, err := tls.ReadKeyFromFile(ncutils.GetNetclientPath() + ncutils.GetSeparator() + "client.key")
if err != nil {
return err
}

View file

@ -20,19 +20,19 @@ func Register(cfg *config.ClientConfig) error {
//generate new key if one doesn' exist
var private *ed25519.PrivateKey
var err error
private, err = tls.ReadKey(ncutils.GetNetclientPath() + ncutils.GetSeparator() + "client.key")
private, err = tls.ReadKeyFromFile(ncutils.GetNetclientPath() + ncutils.GetSeparator() + "client.key")
if err != nil {
_, newKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return err
}
if err := tls.SaveKey(ncutils.GetNetclientPath(), ncutils.GetSeparator()+"client.key", newKey); err != nil {
if err := tls.SaveKeyToFile(ncutils.GetNetclientPath(), ncutils.GetSeparator()+"client.key", newKey); err != nil {
return err
}
private = &newKey
}
//check if cert exists
_, err = tls.ReadCert(ncutils.GetNetclientServerPath(cfg.Server.Server) + ncutils.GetSeparator() + "client.pem")
_, err = tls.ReadCertFromFile(ncutils.GetNetclientServerPath(cfg.Server.Server) + ncutils.GetSeparator() + "client.pem")
if errors.Is(err, os.ErrNotExist) {
if err := RegisterWithServer(private, cfg); err != nil {
return err
@ -88,10 +88,10 @@ func RegisterWithServer(private *ed25519.PrivateKey, cfg *config.ClientConfig) e
//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.GetNetclientServerPath(cfg.Server.Server)+ncutils.GetSeparator(), "root.pem", &resp.CA); err != nil {
if err := tls.SaveCertToFile(ncutils.GetNetclientServerPath(cfg.Server.Server)+ncutils.GetSeparator(), "root.pem", &resp.CA); err != nil {
return err
}
if err := tls.SaveCert(ncutils.GetNetclientServerPath(cfg.Server.Server)+ncutils.GetSeparator(), "client.pem", &resp.Cert); err != nil {
if err := tls.SaveCertToFile(ncutils.GetNetclientServerPath(cfg.Server.Server)+ncutils.GetSeparator(), "client.pem", &resp.Cert); err != nil {
return err
}
logger.Log(0, "certificates/key saved ")

View file

@ -6,6 +6,7 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
@ -14,11 +15,21 @@ import (
"time"
"filippo.io/edwards25519"
"github.com/gravitl/netmaker/database"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
// CERTTIFICAT_VALIDITY duration of certificate validity in days
const CERTIFICATE_VALIDITY = 365
const (
// CERTTIFICATE_VALIDITY duration of certificate validity in days
CERTIFICATE_VALIDITY = 365
// SERVER_KEY_NAME - name of server cert private key
SERVER_KEY_NAME = "serverkey"
// ROOT_KEY_NAME - name of root cert private key
ROOT_KEY_NAME = "rootkey"
)
type (
// Key is the struct for an edwards representation point
@ -189,8 +200,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 {
// SaveCertToFile save a certificate to the specified path
func SaveCertToFile(path, name string, cert *x509.Certificate) error {
//certbytes, err := x509.ParseCertificate(cert)
if err := os.MkdirAll(path, 0600); err != nil {
return fmt.Errorf("failed to create dir %s %w", path, err)
@ -209,8 +220,24 @@ 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 {
// SaveCertToDB - save a certificate to the certs database
func SaveCertToDB(name string, cert *x509.Certificate) error {
if certBytes := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Raw,
}); len(certBytes) > 0 {
data, err := json.Marshal(&certBytes)
if err != nil {
return fmt.Errorf("failed to marshal certificate - %v ", err)
}
return database.Insert(name, string(data), database.CERTS_TABLE_NAME)
} else {
return fmt.Errorf("failed to write cert to DB - %s ", name)
}
}
// SaveKeyToFile save a private key (ed25519) to the certs database
func SaveKeyToFile(path, name string, key ed25519.PrivateKey) error {
//func SaveKey(name string, key *ecdsa.PrivateKey) error {
if err := os.MkdirAll(path, 0600); err != nil {
return fmt.Errorf("failed to create dir %s %w", path, err)
@ -233,8 +260,28 @@ func SaveKey(path, name string, key ed25519.PrivateKey) error {
return nil
}
// ReadCert reads a certificate from disk
func ReadCert(name string) (*x509.Certificate, error) {
// SaveKeyToDB - save a private key (ed25519) to the specified path
func SaveKeyToDB(name string, key ed25519.PrivateKey) error {
privBytes, err := x509.MarshalPKCS8PrivateKey(key)
if err != nil {
return fmt.Errorf("failed to marshal key %v ", err)
}
if pemBytes := pem.EncodeToMemory(&pem.Block{
Type: "PRIVATE KEY",
Bytes: privBytes,
}); len(pemBytes) > 0 {
data, err := json.Marshal(&pemBytes)
if err != nil {
return fmt.Errorf("failed to marshal key %v ", err)
}
return database.Insert(name, string(data), database.CERTS_TABLE_NAME)
} else {
return fmt.Errorf("failed to write key to DB - %v ", err)
}
}
// ReadCertFromFile reads a certificate from disk
func ReadCertFromFile(name string) (*x509.Certificate, error) {
contents, err := os.ReadFile(name)
if err != nil {
return nil, fmt.Errorf("unable to read file %w", err)
@ -250,8 +297,29 @@ 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) {
// ReadCertFromDB - reads a certificate from the database
func ReadCertFromDB(name string) (*x509.Certificate, error) {
certString, err := database.FetchRecord(database.CERTS_TABLE_NAME, name)
if err != nil {
return nil, fmt.Errorf("unable to read file %w", err)
}
var certBytes []byte
if err = json.Unmarshal([]byte(certString), &certBytes); err != nil {
return nil, fmt.Errorf("unable to unmarshal db cert %w", err)
}
block, _ := pem.Decode(certBytes)
if block == nil || block.Type != "CERTIFICATE" {
return nil, errors.New("not a cert " + block.Type)
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("unable to parse cert %w", err)
}
return cert, nil
}
// ReadKeyFromFile reads a private key (ed25519) from disk
func ReadKeyFromFile(name string) (*ed25519.PrivateKey, error) {
bytes, err := os.ReadFile(name)
if err != nil {
return nil, fmt.Errorf("unable to read file %w", err)
@ -265,6 +333,25 @@ func ReadKey(name string) (*ed25519.PrivateKey, error) {
return &private, nil
}
// ReadKeyFromDB - reads a private key (ed25519) from the database
func ReadKeyFromDB(name string) (*ed25519.PrivateKey, error) {
keyString, err := database.FetchRecord(database.CERTS_TABLE_NAME, name)
if err != nil {
return nil, fmt.Errorf("unable to read key value from db - %w", err)
}
var bytes []byte
if err = json.Unmarshal([]byte(keyString), &bytes); err != nil {
return nil, fmt.Errorf("unable to unmarshal db key - %w", err)
}
keyBytes, _ := pem.Decode(bytes)
key, err := x509.ParsePKCS8PrivateKey(keyBytes.Bytes)
if err != nil {
return nil, fmt.Errorf("unable to parse key from DB - %w", err)
}
private := key.(ed25519.PrivateKey)
return &private, nil
}
// serialNumber generates a serial number for a certificate
func serialNumber() *big.Int {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)