mirror of
				https://github.com/gravitl/netmaker.git
				synced 2025-10-31 16:43:07 +08:00 
			
		
		
		
	refactoring cert logic to use database
This commit is contained in:
		
							parent
							
								
									b281047168
								
							
						
					
					
						commit
						f28d361bea
					
				
					 5 changed files with 124 additions and 90 deletions
				
			
		|  | @ -15,6 +15,7 @@ import ( | |||
| 	"github.com/gravitl/netmaker/models" | ||||
| 	"github.com/gravitl/netmaker/netclient/config" | ||||
| 	"github.com/gravitl/netmaker/servercfg" | ||||
| 	"github.com/gravitl/netmaker/serverctl" | ||||
| 	"github.com/gravitl/netmaker/tls" | ||||
| ) | ||||
| 
 | ||||
|  | @ -142,12 +143,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.ReadCertFromFile("/etc/netmaker/root.pem") | ||||
| 	ca, err := serverctl.ReadCertFromDB(tls.ROOT_PEM_NAME) | ||||
| 	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.ReadKeyFromFile("/etc/netmaker/root.key") | ||||
| 	key, err := serverctl.ReadKeyFromDB(tls.ROOT_KEY_NAME) | ||||
| 	if err != nil { | ||||
| 		logger.Log(2, "root key not found ", err.Error()) | ||||
| 		return nil, nil, fmt.Errorf("root key not found %w", err) | ||||
|  |  | |||
							
								
								
									
										14
									
								
								main.go
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								main.go
									
										
									
									
									
								
							|  | @ -190,21 +190,21 @@ func genCerts() error { | |||
| 	logger.Log(0, "checking keys and certificates") | ||||
| 	var private *ed25519.PrivateKey | ||||
| 	var err error | ||||
| 	private, err = tls.ReadKeyFromFile(functions.GetNetmakerPath() + "/root.key") | ||||
| 	private, err = serverctl.ReadKeyFromDB(tls.ROOT_KEY_NAME) | ||||
| 	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.SaveKeyToFile(functions.GetNetmakerPath(), "/root.key", newKey); err != nil { | ||||
| 		if err := serverctl.SaveKey(functions.GetNetmakerPath()+ncutils.GetSeparator(), tls.ROOT_KEY_NAME, newKey); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		private = &newKey | ||||
| 	} else if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	ca, err := tls.ReadCertFromFile(functions.GetNetmakerPath() + ncutils.GetSeparator() + "root.pem") | ||||
| 	ca, err := serverctl.ReadCertFromDB(tls.ROOT_PEM_NAME) | ||||
| 	//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.SaveCertToFile(functions.GetNetmakerPath(), ncutils.GetSeparator()+"root.pem", rootCA); err != nil { | ||||
| 		if err := serverctl.SaveCert(functions.GetNetmakerPath()+ncutils.GetSeparator(), tls.ROOT_PEM_NAME, rootCA); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		ca = rootCA | ||||
| 	} else if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	cert, err := tls.ReadCertFromFile(functions.GetNetmakerPath() + "/server.pem") | ||||
| 	cert, err := serverctl.ReadCertFromDB(tls.SERVER_PEM_NAME) | ||||
| 	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.SaveKeyToFile(functions.GetNetmakerPath(), "/server.key", key); err != nil { | ||||
| 		if err := serverctl.SaveKey(functions.GetNetmakerPath()+ncutils.GetSeparator(), tls.SERVER_KEY_NAME, key); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := tls.SaveCertToFile(functions.GetNetmakerPath(), "/server.pem", cert); err != nil { | ||||
| 		if err := serverctl.SaveCert(functions.GetNetmakerPath()+ncutils.GetSeparator(), tls.SERVER_PEM_NAME, cert); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} else if err != nil { | ||||
|  |  | |||
|  | @ -88,7 +88,7 @@ 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.SaveCertToFile(ncutils.GetNetclientServerPath(cfg.Server.Server)+ncutils.GetSeparator(), "root.pem", &resp.CA); err != nil { | ||||
| 	if err := tls.SaveCertToFile(ncutils.GetNetclientServerPath(cfg.Server.Server)+ncutils.GetSeparator(), tls.ROOT_PEM_NAME, &resp.CA); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := tls.SaveCertToFile(ncutils.GetNetclientServerPath(cfg.Server.Server)+ncutils.GetSeparator(), "client.pem", &resp.Cert); err != nil { | ||||
|  |  | |||
							
								
								
									
										105
									
								
								serverctl/tls.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								serverctl/tls.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,105 @@ | |||
| package serverctl | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/ed25519" | ||||
| 	"crypto/x509" | ||||
| 	"encoding/json" | ||||
| 	"encoding/pem" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/gravitl/netmaker/database" | ||||
| 	"github.com/gravitl/netmaker/tls" | ||||
| ) | ||||
| 
 | ||||
| // SaveCert - save a certificate to file and DB | ||||
| func SaveCert(path, name string, cert *x509.Certificate) error { | ||||
| 	if err := SaveCertToDB(name, cert); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return tls.SaveCertToFile(path, name, cert) | ||||
| } | ||||
| 
 | ||||
| // 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) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SaveKey - save a private key (ed25519) to file and DB | ||||
| func SaveKey(path, name string, key ed25519.PrivateKey) error { | ||||
| 	if err := SaveKeyToDB(name, key); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return tls.SaveKeyToFile(path, name, key) | ||||
| } | ||||
| 
 | ||||
| // 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) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // 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 | ||||
| } | ||||
| 
 | ||||
| // 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 | ||||
| } | ||||
							
								
								
									
										88
									
								
								tls/tls.go
									
										
									
									
									
								
							
							
						
						
									
										88
									
								
								tls/tls.go
									
										
									
									
									
								
							|  | @ -6,7 +6,6 @@ import ( | |||
| 	"crypto/x509" | ||||
| 	"crypto/x509/pkix" | ||||
| 	"encoding/base64" | ||||
| 	"encoding/json" | ||||
| 	"encoding/pem" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
|  | @ -15,7 +14,6 @@ import ( | |||
| 	"time" | ||||
| 
 | ||||
| 	"filippo.io/edwards25519" | ||||
| 	"github.com/gravitl/netmaker/database" | ||||
| 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes" | ||||
| ) | ||||
| 
 | ||||
|  | @ -25,10 +23,16 @@ const ( | |||
| 	CERTIFICATE_VALIDITY = 365 | ||||
| 
 | ||||
| 	// SERVER_KEY_NAME - name of server cert private key | ||||
| 	SERVER_KEY_NAME = "serverkey" | ||||
| 	SERVER_KEY_NAME = "server.key" | ||||
| 
 | ||||
| 	// ROOT_KEY_NAME - name of root cert private key | ||||
| 	ROOT_KEY_NAME = "rootkey" | ||||
| 	ROOT_KEY_NAME = "root.key" | ||||
| 
 | ||||
| 	// SERVER_PEM_NAME - name of server pem | ||||
| 	SERVER_PEM_NAME = "server.pem" | ||||
| 
 | ||||
| 	// ROOT_PEM_NAME - name of root pem | ||||
| 	ROOT_PEM_NAME = "root.pem" | ||||
| ) | ||||
| 
 | ||||
| type ( | ||||
|  | @ -220,22 +224,6 @@ func SaveCertToFile(path, name string, cert *x509.Certificate) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // 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 { | ||||
|  | @ -260,26 +248,6 @@ func SaveKeyToFile(path, name string, key ed25519.PrivateKey) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // 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) | ||||
|  | @ -297,27 +265,6 @@ func ReadCertFromFile(name string) (*x509.Certificate, error) { | |||
| 	return cert, nil | ||||
| } | ||||
| 
 | ||||
| // 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) | ||||
|  | @ -333,25 +280,6 @@ func ReadKeyFromFile(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) | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue