diff --git a/swiftwave_service/core/domain.operations.go b/swiftwave_service/core/domain.operations.go index 9f4256a027..751e4f08a6 100644 --- a/swiftwave_service/core/domain.operations.go +++ b/swiftwave_service/core/domain.operations.go @@ -5,8 +5,10 @@ import ( "crypto/x509" "encoding/pem" "errors" - "gorm.io/gorm" + "strings" "time" + + "gorm.io/gorm" ) // This file contains the operations for the Domain model. @@ -33,7 +35,7 @@ func (domain *Domain) FindById(_ context.Context, db gorm.DB, id uint) error { } func (domain *Domain) Create(_ context.Context, db gorm.DB) error { - err := domain.fillSSLInfo() + err := domain.validateAndFillSSLInfo() if err != nil { return err } @@ -42,7 +44,7 @@ func (domain *Domain) Create(_ context.Context, db gorm.DB) error { } func (domain *Domain) Update(_ context.Context, db gorm.DB) error { - err := domain.fillSSLInfo() + err := domain.validateAndFillSSLInfo() if err != nil { return err } @@ -66,16 +68,58 @@ func (domain *Domain) Delete(_ context.Context, db gorm.DB) error { func (domain *Domain) UpdateSSLStatus(_ context.Context, db gorm.DB, status DomainSSLStatus) error { domain.SSLStatus = status - tx := db.Where("id = ?", domain.ID).Update("ssl_status", status) + tx := db.Model(&domain).Where("id = ?", domain.ID).Update("ssl_status", status) return tx.Error } -func (domain *Domain) fillSSLInfo() error { +func (domain *Domain) validateAndFillSSLInfo() error { if domain == nil || domain.SSLFullChain == "" { return nil } + + // if ssl full chain or private key is missing \n at the end , add it + if !strings.HasSuffix(domain.SSLFullChain, "\n") { + domain.SSLFullChain = domain.SSLFullChain + "\n" + } + if !strings.HasSuffix(domain.SSLPrivateKey, "\n") { + domain.SSLPrivateKey = domain.SSLPrivateKey + "\n" + } + + // validate private key + keyBytes := []byte(domain.SSLPrivateKey) + block, _ := pem.Decode(keyBytes) + if block == nil { + return errors.New("failed to decode SSL private key") + } + // Attempt parsing the key as any supported private key format + isValidated := false + _, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err == nil { + isValidated = true // Key is valid PKCS8 + } + + if !isValidated { + + _, err = x509.ParsePKCS1PrivateKey(block.Bytes) + if err == nil { + isValidated = true // Key is valid PKCS1 + } + } + + if !isValidated { + _, err = x509.ParseECPrivateKey(block.Bytes) + if err == nil { + isValidated = true // Key is valid EC + } + } + + if !isValidated { + return errors.New("provided private keys is not a valid private key (RSA, PKCS8, PKCS1, or EC)") + } + + // validate full chain certificate certBytes := []byte(domain.SSLFullChain) - block, _ := pem.Decode(certBytes) + block, _ = pem.Decode(certBytes) if block == nil { return errors.New("failed to decode SSL full chain certificate") } diff --git a/swiftwave_service/graphql/domain.resolvers.go b/swiftwave_service/graphql/domain.resolvers.go index bea2475944..26cb4e6bbb 100644 --- a/swiftwave_service/graphql/domain.resolvers.go +++ b/swiftwave_service/graphql/domain.resolvers.go @@ -113,17 +113,7 @@ func (r *mutationResolver) AddCustomSsl(ctx context.Context, id uint, input mode if err != nil { return nil, err } - // validate certificate full chain - err = ValidateSSLFullChainCertificate(input.FullChain) - if err != nil { - return nil, err - } - // validate certificate private key - err = ValidateSSLPrivateKey(input.PrivateKey) - if err != nil { - return nil, err - } // update record record.SSLPrivateKey = input.PrivateKey record.SSLFullChain = input.FullChain diff --git a/swiftwave_service/graphql/helpers.go b/swiftwave_service/graphql/helpers.go index b3468c53e4..5f84bfa1c7 100644 --- a/swiftwave_service/graphql/helpers.go +++ b/swiftwave_service/graphql/helpers.go @@ -2,7 +2,6 @@ package graphql import ( "context" - "encoding/pem" "errors" "fmt" "log" @@ -18,7 +17,6 @@ import ( "github.com/swiftwave-org/swiftwave/swiftwave_service/graphql/model" "github.com/swiftwave-org/swiftwave/swiftwave_service/logger" "github.com/swiftwave-org/swiftwave/swiftwave_service/manager" - "golang.org/x/crypto/ssh" "gorm.io/gorm" ) @@ -55,37 +53,6 @@ func sanitizeFileName(fileName string) string { return fileName } -func ValidateSSLFullChainCertificate(certString string) error { - // Parse the SSL public key (including certificates) - pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(certString)) - if err != nil { - return fmt.Errorf("failed to parse SSL public key: %v", err) - } - - // Check if it's an SSH certificate - _, ok := pubKey.(*ssh.Certificate) - if !ok { - return fmt.Errorf("provided file is not an SSL certificate") - } - - return nil -} - -func ValidateSSLPrivateKey(privateKeyString string) error { - // Decode the PEM block - block, _ := pem.Decode([]byte(privateKeyString)) - if block == nil { - return fmt.Errorf("failed to decode PEM block from private key") - } - - // Try to parse the key as an SSH private key - _, err := ssh.ParseRawPrivateKey(block.Bytes) - if err != nil { - return fmt.Errorf("failed to parse SSL private key: %v", err) - } - return nil -} - func FetchDockerManager(ctx context.Context, db *gorm.DB) (*containermanger.Manager, error) { // Fetch a random swarm manager swarmManagerServer, err := core.FetchSwarmManager(db) diff --git a/swiftwave_service/worker/init.go b/swiftwave_service/worker/init.go index 0bf085ed41..e7ec6685a9 100644 --- a/swiftwave_service/worker/init.go +++ b/swiftwave_service/worker/init.go @@ -62,6 +62,7 @@ func Queues() []string { redirectRuleApplyQueueName, redirectRuleDeleteQueueName, sslGenerateQueueName, + sslProxyUpdateQueueName, deletePersistentVolumeQueueName, persistentVolumeBackupQueueName, persistentVolumeRestoreQueueName,