diff --git a/.gitignore b/.gitignore index 941c7cd..25c80a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ dist/appviewx-csi-provider dist/vault-csi-provider +notes diff --git a/dev_README.md b/dev_README.md index 1eb0a48..bd6d1d3 100644 --- a/dev_README.md +++ b/dev_README.md @@ -13,6 +13,10 @@ W1- cert-orchestrator-install Create CA Setting kubectl apply -f ./005_appviewx/casetting/ + Add Renewaljob + kubectl apply -f ./012_renewal_appviewx/renewaljob/cert-orchestrator_v1_renewaljob.yaml + + R2 - logs cd /tmp;\ kubectl logs $(kubectl get pods -n cert-orchestrator-system | awk '{ if(NR==2) print $1}' ) -n cert-orchestrator-system -c manager > /tmp/cert-orchestrator/log.txt && kubectl logs -f $(kubectl get pods -n cert-orchestrator-system | awk '{ if(NR==2) print $1}' ) -n cert-orchestrator-system -c manager >> /tmp/cert-orchestrator/log.txt; @@ -152,7 +156,7 @@ metadata: spec: provider: appviewx parameters: - objectFormat: pem # pem, pfx + objectFormat: pem # pem, pfx, jks objectEncoding: utf-8 # utf-8, hex, base64 objects: | - commonName: cert-default-leaf-casetting-default-ca-casetting-default-selfsigned.appviewx.com @@ -224,7 +228,7 @@ kubectl apply -f webapp-pod.yaml R2 - logs cd /tmp - kubectl get pods | grep provider | awk '{print $1}' | xargs kubectl logs -f + kubectl get pods -A | grep orches | awk '{print $2}' | xargs kubectl logs -f -n cert-orchestrator-system -c manager kubectl get pods -n appviewx-csi-provider| grep appviewx-csi-provider- | awk '{print $1}' | xargs kubectl logs -f -n appviewx-csi-provider @@ -236,7 +240,7 @@ kubectl apply -f webapp-pod.yaml Performance - Logs Logs - provider and cert-orchestrator - kubectl get pods -A | grep provider | awk '{print $2}' | xargs kubectl logs -f + kubectl get pods -A | grep appviewx-csi-provider- | awk '{print $2}' | xargs kubectl logs -f -n appviewx-csi-provider kubectl get pods -A | grep orches | awk '{print $2}' | xargs kubectl logs -f -n cert-orchestrator-system -c manager Watch diff --git a/go.mod b/go.mod index e4ba465..f1a318d 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/hashicorp/go-hclog v1.0.0 github.com/hashicorp/vault/api v1.2.0 github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect + github.com/pavlo-v-chernykh/keystore-go/v4 v4.4.0 // indirect github.com/stretchr/testify v1.7.2 google.golang.org/grpc v1.41.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index fcd76bd..36781d3 100644 --- a/go.sum +++ b/go.sum @@ -617,6 +617,8 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pavlo-v-chernykh/keystore-go/v4 v4.4.0 h1:y9azNmMzvkNBPyczpNRwaV4bm0U6e7Oyrj7gi2/SNFI= +github.com/pavlo-v-chernykh/keystore-go/v4 v4.4.0/go.mod h1:lAVhWwbNaveeJmxrxuSTxMgKpF6DjnuVpn6T8WiBwYQ= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= diff --git a/internal/config/config.go b/internal/config/config.go index 7243ba5..bc50030 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -131,9 +131,12 @@ func (c *Config) validate() error { fmt.Printf("ObjectFormat is not given : Setting : %s\n", util.OBJECT_FORMAT_PEM) c.Parameters.ObjectFormat = util.OBJECT_FORMAT_PEM } else if strings.ToLower(c.Parameters.ObjectFormat) != util.OBJECT_FORMAT_PEM && - strings.ToLower(c.Parameters.ObjectFormat) != util.OBJECT_FORMAT_PFX { + strings.ToLower(c.Parameters.ObjectFormat) != util.OBJECT_FORMAT_PFX && + strings.ToLower(c.Parameters.ObjectFormat) != util.OBJECT_FORMAT_JKS { - return fmt.Errorf("%s : is not a valid ObjectFormat", c.Parameters.ObjectFormat) + return fmt.Errorf("%s : is not a valid ObjectFormat only %s,%s,%s are supported", + c.Parameters.ObjectFormat, + util.OBJECT_FORMAT_PEM, util.OBJECT_FORMAT_PFX, util.OBJECT_FORMAT_JKS) } if len(c.Parameters.ObjectEncoding) == 0 { @@ -143,7 +146,10 @@ func (c *Config) validate() error { strings.ToLower(c.Parameters.ObjectEncoding) != util.OBJECT_ENCODING_HEX && strings.ToLower(c.Parameters.ObjectEncoding) != util.OBJECT_ENCODING_BASE_64 { - return fmt.Errorf("%s : is not a valid ObjectEncoding", c.Parameters.ObjectEncoding) + return fmt.Errorf("%s : is not a valid ObjectEncoding only %s,%s,%s are supported", + c.Parameters.ObjectEncoding, + util.OBJECT_ENCODING_UTF_8, util.OBJECT_ENCODING_HEX, util.OBJECT_ENCODING_BASE_64, + ) } return nil diff --git a/internal/format/jks.go b/internal/format/jks.go new file mode 100644 index 0000000..81a3b43 --- /dev/null +++ b/internal/format/jks.go @@ -0,0 +1,178 @@ +package format + +import ( + "bytes" + "crypto/rsa" + "crypto/x509" + "encoding/asn1" + "encoding/pem" + "fmt" + "math/rand" + "time" + + "github.com/hashicorp/go-hclog" + "github.com/pavlo-v-chernykh/keystore-go/v4" + + "github.com/AppViewX/appviewx-csi-provider/internal/util" +) + +const ( + ALIAS_NAME = "tls1" +) + +type Rand struct { +} + +type PKCS8Key struct { + Version int + PrivateKeyAlgorithm []asn1.ObjectIdentifier + PrivateKey []byte +} + +func (r Rand) Read(p []byte) (n int, err error) { + for i := range p { + p[i] = byte(rand.Int31n(9)) + } + return len(p), nil +} + +func marshalPKCS8PrivateKey(key *rsa.PrivateKey, l hclog.Logger) ([]byte, error) { + l.Debug("Starting marshalPKCS8PrivateKey") + var pkey PKCS8Key + pkey.Version = 0 + pkey.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 1) + pkey.PrivateKeyAlgorithm[0] = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} + pkey.PrivateKey = x509.MarshalPKCS1PrivateKey(key) + output, err := asn1.Marshal(pkey) + if err != nil { + l.Error("Error in marshalPKCS8PrivateKey while asn1.Marshal : %v", err) + return nil, fmt.Errorf("error in marshalPKCS8PrivateKey while asn1.Marshal : %w", err) + } + l.Debug("Finished marshalPKCS8PrivateKey") + return output, nil +} + +func getPrivateKey(privateKeyFileContents []byte, l hclog.Logger) ([]byte, error) { + l.Debug("Starting getPrivateKey") + block, _ := pem.Decode(privateKeyFileContents) + if block == nil { + l.Error("Should have one pem block : error in getPrivateKey ") + return nil, fmt.Errorf("should have one pem block : error in getPrivateKey") + } + + priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + l.Error(fmt.Sprintf("Error in getPrivateKey while x509.ParsePKCS1PrivateKey : %v", err)) + return nil, fmt.Errorf("error in getPrivateKey while x509.ParsePKCS1PrivateKey : %w", err) + } + + output, err := marshalPKCS8PrivateKey(priv, l) + if err != nil { + l.Error(fmt.Sprintf("Error in getPrivateKey while marshalPKCS8PrivateKey : %v", err)) + return nil, fmt.Errorf("error in getPrivateKey while marshalPKCS8PrivateKey : %w", err) + } + l.Debug("Finished getPrivateKey") + return output, nil +} + +func getKeyStoreCertificate( + certificateFileContents, caCertificateFileContents []byte, + l hclog.Logger, +) ([]keystore.Certificate, error) { + + l.Debug("Started getKeyStoreCertificate") + + certificateChain := []keystore.Certificate{} + + l.Debug("Adding Leaf Certificate") + block, _ := pem.Decode(certificateFileContents) + if block == nil { + l.Error("block should not be empty - Error in getKeyStoreCertificate while pem.Decode(certificateFileContents)") + return nil, fmt.Errorf("block should not be empty - Error in getKeyStoreCertificate while pem.Decode(certificateFileContents)") + } + certificateDecodedContents := block.Bytes + certificateChain = append(certificateChain, keystore.Certificate{ + Type: "X509", + Content: certificateDecodedContents}) + + l.Debug("Adding Root and Intermediate Certificate") + + for { + var certDERBlock *pem.Block + certDERBlock, caCertificateFileContents = pem.Decode(caCertificateFileContents) + if certDERBlock == nil { + break + } + certificateChain = append(certificateChain, keystore.Certificate{ + Type: "X509", + Content: certDERBlock.Bytes}) + } + l.Debug("Added Root and Intermediate Certificate") + + return certificateChain, nil +} + +func GetJKSKeyStoreContents( + currentSecretContent map[string][]byte, + l hclog.Logger, +) ( + jksContents []byte, + jksPassword, aliasName, aliasPassword string, + err error, +) { + + l.Info("Starting GetJKSKeyStoreContents") + + keyStoreInstance := keystore.New( + keystore.WithOrderedAliases(), + keystore.WithCustomRandomNumberGenerator(Rand{}), + ) + + currentTime := time.Now() + + privateKeyFileContents, certificateFileContents, caCertificateFileContents, err := + getPrivateKeyCertificateAndCACertificates(currentSecretContent, l) + if err != nil { + l.Error(fmt.Sprintf("Error in GetJKSKeyStoreContents while getPrivateKeyCertificateAndCACertificates : %v", err)) + return nil, "", "", "", fmt.Errorf("error in GetJKSKeyStoreContents while getPrivateKeyCertificateAndCACertificates : %w", err) + } + + certificateChain, err := getKeyStoreCertificate(certificateFileContents, caCertificateFileContents, l) + if err != nil { + l.Error(fmt.Sprintf("Error in GetJKSKeyStoreContents while getKeyStoreCertificate : %v", err)) + return nil, "", "", "", fmt.Errorf("error in GetJKSKeyStoreContents while getKeyStoreCertificate : %w", err) + } + + privateKey, err := getPrivateKey(privateKeyFileContents, l) + if err != nil { + l.Error(fmt.Sprintf("Error in GetJKSKeyStoreContents while getPrivateKey : %v", err)) + return nil, "", "", "", fmt.Errorf("error in GetJKSKeyStoreContents while getPrivateKey : %w", err) + } + + privateKeyEntry := keystore.PrivateKeyEntry{ + CreationTime: currentTime, + PrivateKey: privateKey, + CertificateChain: certificateChain, + } + + aliasPassword = util.GetRandomString() + + err = keyStoreInstance.SetPrivateKeyEntry(ALIAS_NAME, privateKeyEntry, []byte(aliasPassword)) + if err != nil { + l.Error(fmt.Sprintf("error in GetJKSKeyStoreContents while keyStoreInstance.SetPrivateKeyEntry : %v", err)) + return nil, "", "", "", fmt.Errorf("error in GetJKSKeyStoreContents while keyStoreInstance.SetPrivateKeyEntry : %w", err) + } + + jksPassword = util.GetRandomString() + var buffer bytes.Buffer + + err = keyStoreInstance.Store(&buffer, []byte(jksPassword)) + if err != nil { + l.Error(fmt.Sprintf("error in GetJKSKeyStoreContents while keyStoreInstance.Store : %v", err)) + return nil, "", "", "", fmt.Errorf("error in GetJKSKeyStoreContents while keyStoreInstance.Store : %w", err) + } + + l.Info("Finished GetJKSKeyStoreContents") + + return buffer.Bytes(), jksPassword, ALIAS_NAME, aliasPassword, nil +} diff --git a/internal/format/pfx.go b/internal/format/pfx.go new file mode 100644 index 0000000..67ffa66 --- /dev/null +++ b/internal/format/pfx.go @@ -0,0 +1,131 @@ +package format + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "fmt" + "log" + + "github.com/hashicorp/go-hclog" + "software.sslmate.com/src/go-pkcs12" + + "github.com/AppViewX/appviewx-csi-provider/internal/util" +) + +func getPrivateKeyCertificateAndCACertificates( + currentSecretContent map[string][]byte, + l hclog.Logger, +) ( + privateKeyFileContents, certificateFileContents, caCertificateFileContents []byte, + err error, +) { + var ok bool + privateKeyFileContents, ok = currentSecretContent["tls.key"] + if !ok || len(privateKeyFileContents) <= 0 { + l.Error("error in getPrivateKeyCertificateAndCACertificates tls.key is not available") + return nil, nil, nil, fmt.Errorf("error in getPrivateKeyCertificateAndCACertificates : tls.key is not available ") + } + + certificateFileContents, ok = currentSecretContent["tls.crt"] + if !ok || len(certificateFileContents) <= 0 { + l.Error("error in getPrivateKeyCertificateAndCACertificates tls.crt is not available") + return nil, nil, nil, fmt.Errorf("error in getPrivateKeyCertificateAndCACertificates : tls.crt is not available") + } + + caCertificateFileContents, ok = currentSecretContent["ca.crt"] + if !ok || len(caCertificateFileContents) <= 0 { + l.Error("error in getPrivateKeyCertificateAndCACertificates ca.crt is not available") + return nil, nil, nil, fmt.Errorf("error in getPrivateKeyCertificateAndCACertificates ca.crt is not available") + } + return +} + +func GetPfxContentForSecret(currentSecretContent map[string][]byte, l hclog.Logger) ([]byte, string, error) { + + l.Debug("Starting getPfxContentForSecret") + + privateKeyFileContents, certificateFileContents, caCertificateFileContents, err := + getPrivateKeyCertificateAndCACertificates(currentSecretContent, l) + if err != nil { + l.Error(fmt.Sprintf("Error in GetPfxContentForSecret while getPrivateKeyCertificateAndCACertificates : %v", err)) + return nil, "", fmt.Errorf("error in GetPfxContentForSecret while getPrivateKeyCertificateAndCACertificates : %w", err) + } + + block, _ := pem.Decode(privateKeyFileContents) + if block == nil { + l.Error("error in GetPfxContentForSecret while Decoding PrivateKey") + return nil, "", fmt.Errorf("error in GetPfxContentForSecret while Decoding PrivateKey") + } + + var keyBytes *rsa.PrivateKey + if block != nil { + keyBytes, err = x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + l.Debug("Error in GetPfxContentForSecret while ParsePKCS1PrivateKey: %v", err) + return nil, "", fmt.Errorf("error in GetPfxContentForSecret while ParsePKCS1PrivateKey : %w", err) + } + } + + signedCert, err := getCertificateFromContents(certificateFileContents, l) + if err != nil { + log.Println("Error in GetPfxContentForSecret while getCertificateFromContents", err) + return nil, "", fmt.Errorf("error in GetPfxContentForSecret while getCertificateFromContents : %w", err) + } + + caCerts, err := getCACerts(caCertificateFileContents, l) + if err != nil { + log.Println("Error in GetPfxContentForSecret while getCACerts", err) + return nil, "", fmt.Errorf("error in GetPfxContentForSecret while getCACerts : %w", err) + } + + password := util.GetRandomString() + + l.Info("Generating the pfx file") + pfxData, err := pkcs12.Encode(rand.Reader, keyBytes, signedCert, caCerts, password) + if err != nil { + log.Println("Error in GetPfxContentForSecret while pkcs12.Encode", err) + return nil, "", fmt.Errorf("error in GetPfxContentForSecret while pkcs12.Encode : %w", err) + } + + l.Debug("Finished GetPfxContentForSecret") + return pfxData, password, nil +} + +func getCertificateFromContents(certificateContents []byte, l hclog.Logger) (cert *x509.Certificate, err error) { + l.Debug("Starting getCertificateFromContents") + block, _ := pem.Decode(certificateContents) + cert, err = x509.ParseCertificate(block.Bytes) + if err != nil { + l.Error(fmt.Sprintf("error in getCertificateFromContents while ParseCertificate : %v", err)) + return nil, fmt.Errorf("error in getCertificateFromContents while ParseCertificate : %w", err) + } + l.Debug("Finished getCertificateFromContents") + return +} + +func getCACerts(caCertificateFileContents []byte, l hclog.Logger) (output []*x509.Certificate, err error) { + l.Debug("Starting getCACerts") + var blocks [][]byte + + for { + var certDERBlock *pem.Block + certDERBlock, caCertificateFileContents = pem.Decode(caCertificateFileContents) + if certDERBlock == nil { + break + } + blocks = append(blocks, certDERBlock.Bytes) + } + + for _, block := range blocks { + cert, err := x509.ParseCertificate(block) + if err != nil { + l.Error("Error in getCACerts while ParseCertificate : %v", err) + return nil, fmt.Errorf("error in getCACerts while parseCertificate : %w", err) + } + output = append(output, cert) + } + l.Debug("Finished getCACerts") + return +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index d9c6152..8d56f7d 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -2,15 +2,9 @@ package provider import ( "context" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/base64" - "encoding/hex" - "encoding/pem" "flag" "fmt" - "log" + "io/fs" "strings" "sync" "time" @@ -28,11 +22,11 @@ import ( clientConfig "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" pb "sigs.k8s.io/secrets-store-csi-driver/provider/v1alpha1" - "software.sslmate.com/src/go-pkcs12" certorchestratorv1 "github.com/AppViewX/appviewx-csi-provider/cert-orchestrator/api/v1" v1 "github.com/AppViewX/appviewx-csi-provider/cert-orchestrator/api/v1" "github.com/AppViewX/appviewx-csi-provider/internal/config" + "github.com/AppViewX/appviewx-csi-provider/internal/format" "github.com/AppViewX/appviewx-csi-provider/internal/util" ) @@ -373,6 +367,21 @@ func (p *provider) HandleMountRequest( }, nil } +func appendToFilesAndObjectVersions( + filePermission fs.FileMode, + content []byte, + name string, + files []*pb.File, + objectVersions []*pb.ObjectVersion, +) ([]*pb.File, []*pb.ObjectVersion) { + + files = append(files, &pb.File{Path: name, Mode: int32(filePermission), Contents: content}) + objectVersions = append(objectVersions, &pb.ObjectVersion{ + Id: name, Version: util.GetMD5Hash(content), + }) + return files, objectVersions +} + func getMountFilesAndObjectVersions( cfg config.Config, secretContents []map[string][]byte, @@ -388,17 +397,13 @@ func getMountFilesAndObjectVersions( for k, v := range currentSecretContent { - encodedContent, err := encode(v, encodingFormat, l) + encodedContent, err := util.Encode(v, encodingFormat, l) if err != nil { l.Error(fmt.Sprintf("Error in getMountFilesAndObjectVersions while encode : %v", err)) return nil, nil, fmt.Errorf("error in getMountFilesAndObjectVersions while encode : %w", err) } - files = append(files, &pb.File{Path: k, Mode: int32(cfg.FilePermission), Contents: encodedContent}) - - objectVersions = append(objectVersions, &pb.ObjectVersion{ - Id: k, Version: util.GetMD5Hash(encodedContent), - }) + files, objectVersions = appendToFilesAndObjectVersions(cfg.FilePermission, encodedContent, k, files, objectVersions) } //TODO: Need to handle for multiple secrets break @@ -408,158 +413,47 @@ func getMountFilesAndObjectVersions( l.Info("objectFormat pfx") for _, currentSecretContent := range secretContents { - pfxContent, password, err := getPfxContentForSecret(currentSecretContent, l) + pfxContent, password, err := format.GetPfxContentForSecret(currentSecretContent, l) if err != nil { - l.Error(fmt.Sprintf("Error in getMountFilesAndObjectVersions while getPfxContentForSecret : %v", err)) - return nil, nil, fmt.Errorf("error in getMountFilesAndObjectVersions while getPfxContentForSecret : %w", err) + l.Error(fmt.Sprintf("Error in getMountFilesAndObjectVersions while format.GetPfxContentForSecret : %v", err)) + return nil, nil, fmt.Errorf("error in getMountFilesAndObjectVersions while format.GetPfxContentForSecret : %w", err) } - encodedContent, err := encode(pfxContent, encodingFormat, l) + encodedContent, err := util.Encode(pfxContent, encodingFormat, l) if err != nil { - l.Error(fmt.Sprintf("Error in getMountFilesAndObjectVersions while encode : %v", err)) - return nil, nil, fmt.Errorf("error in getMountFilesAndObjectVersions while encode : %w", err) + l.Error(fmt.Sprintf("Error in getMountFilesAndObjectVersions while util.Encode : %v", err)) + return nil, nil, fmt.Errorf("error in getMountFilesAndObjectVersions while util.Encode : %w", err) } - files = append(files, &pb.File{Path: "tls.pfx", Mode: int32(cfg.FilePermission), Contents: encodedContent}) - objectVersions = append(objectVersions, &pb.ObjectVersion{ - Id: "tls.pfx", Version: util.GetMD5Hash(encodedContent), - }) - - files = append(files, &pb.File{Path: "password", Mode: int32(cfg.FilePermission), Contents: []byte(password)}) - objectVersions = append(objectVersions, &pb.ObjectVersion{ - Id: "password", Version: util.GetMD5Hash([]byte(password)), - }) - + files, objectVersions = appendToFilesAndObjectVersions(cfg.FilePermission, encodedContent, "tls.pfx", files, objectVersions) + files, objectVersions = appendToFilesAndObjectVersions(cfg.FilePermission, []byte(password), "password", files, objectVersions) } return - default: - err = fmt.Errorf("Only pem and pfx 'objectFormat' are supported : %s is not supported", strings.ToLower(cfg.Parameters.ObjectFormat)) - return - } -} - -func getPfxContentForSecret(currentSecretContent map[string][]byte, l hclog.Logger) (pfxContents []byte, password string, err error) { - - l.Debug("Starting getPfxContentForSecret") - - privateKeyFileContents, ok := currentSecretContent["tls.key"] - if !ok { - l.Error("error in getPfxContentForSecret tls.key is not available") - return nil, "", fmt.Errorf("error in getPfxContentForSecret : tls.key is not available ") - } - - certificateFileContents, ok := currentSecretContent["tls.crt"] - if !ok { - l.Error("error in getPfxContentForSecret tls.crt is not available") - return nil, "", fmt.Errorf("error in getPfxContentForSecret : tls.crt is not available") - } - - caCertificateFileContents, ok := currentSecretContent["ca.crt"] - if !ok { - l.Error("error in getPfxContentForSecret ca.crt is not available") - return nil, "", fmt.Errorf("error in getPfxContentForSecret ca.crt is not available") - } - - block, _ := pem.Decode(privateKeyFileContents) - if block == nil { - l.Error("error in getPfxContentForSecret while Decoding PrivateKey") - return nil, "", fmt.Errorf("error in getPfxContentForSecret while Decoding PrivateKey") - } - - var keyBytes *rsa.PrivateKey - if block != nil { - keyBytes, err = x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - l.Debug("Error in getPfxContentForSecret while ParsePKCS1PrivateKey: %v", err) - return nil, "", fmt.Errorf("error in getPfxContentForSecret while ParsePKCS1PrivateKey : %w", err) - } - } - - signedCert, err := getCertificateFromContents(certificateFileContents, l) - if err != nil { - log.Println("Error in getPfxContentForSecret while getCertificateFromContents", err) - return nil, "", fmt.Errorf("error in getPfxContentForSecret while getCertificateFromContents : %w", err) - } - - caCerts, err := getCACerts(caCertificateFileContents, l) - if err != nil { - log.Println("Error in getPfxContentForSecret while getCACerts", err) - return nil, "", fmt.Errorf("error in getPfxContentForSecret while getCACerts : %w", err) - } + case util.OBJECT_FORMAT_JKS: + l.Info("objectFormat jks") - password = util.GetRandomString() - - l.Info("Generating the pfx file") - pfxData, err := pkcs12.Encode(rand.Reader, keyBytes, signedCert, caCerts, password) - if err != nil { - log.Println("Error in getPfxContentForSecret while pkcs12.Encode", err) - return nil, "", fmt.Errorf("error in getPfxContentForSecret while pkcs12.Encode : %w", err) - } - - l.Debug("Finished getPfxContentForSecret") - return pfxData, password, nil -} - -func getCACerts(caCertificateFileContents []byte, l hclog.Logger) (output []*x509.Certificate, err error) { - l.Debug("Starting getCACerts") - var blocks [][]byte + for _, currentSecretContent := range secretContents { + jksContents, jksPassword, aliasName, aliasPassword, err := format.GetJKSKeyStoreContents(currentSecretContent, l) + if err != nil { + l.Error(fmt.Sprintf("Error in getMountFilesAndObjectVersions while format.GetJKSKeyStoreContents : %v", err)) + return nil, nil, fmt.Errorf("error in getMountFilesAndObjectVersions while format.GetJKSKeyStoreContents : %w", err) + } - for { - var certDERBlock *pem.Block - certDERBlock, caCertificateFileContents = pem.Decode(caCertificateFileContents) - if certDERBlock == nil { - break - } - blocks = append(blocks, certDERBlock.Bytes) - } + encodedContent, err := util.Encode(jksContents, encodingFormat, l) + if err != nil { + l.Error(fmt.Sprintf("Error in getMountFilesAndObjectVersions while util.Encode : %v", err)) + return nil, nil, fmt.Errorf("error in getMountFilesAndObjectVersions while util.Encode : %w", err) + } - for _, block := range blocks { - cert, err := x509.ParseCertificate(block) - if err != nil { - l.Error("Error in getCACerts while ParseCertificate : %v", err) - return nil, fmt.Errorf("error in getCACerts while parseCertificate : %w", err) + files, objectVersions = appendToFilesAndObjectVersions(cfg.FilePermission, encodedContent, "tls.jks", files, objectVersions) + files, objectVersions = appendToFilesAndObjectVersions(cfg.FilePermission, []byte(jksPassword), "jksPassword", files, objectVersions) + files, objectVersions = appendToFilesAndObjectVersions(cfg.FilePermission, []byte(aliasName), "aliasName", files, objectVersions) + files, objectVersions = appendToFilesAndObjectVersions(cfg.FilePermission, []byte(aliasPassword), "aliasPassword", files, objectVersions) } - output = append(output, cert) - } - l.Debug("Finished getCACerts") - return -} - -func getCertificateFromContents(certificateContents []byte, l hclog.Logger) (cert *x509.Certificate, err error) { - l.Debug("Starting GetCertificateFromContents") - block, _ := pem.Decode(certificateContents) - cert, err = x509.ParseCertificate(block.Bytes) - if err != nil { - l.Error(fmt.Sprintf("error in GetCertificateFromContents while ParseCertificate : %v", err)) - return nil, fmt.Errorf("error in GetCertificateFromContents while ParseCertificate : %w", err) - } - l.Debug("Finished GetCertificateFromContents") - return -} - -func encode(input []byte, objectEncodingFormat string, l hclog.Logger) (output []byte, err error) { - l.Debug("Starting encode") - - switch objectEncodingFormat { - - case util.OBJECT_ENCODING_BASE_64: - l.Info(fmt.Sprintf("Doing : %s", util.OBJECT_ENCODING_BASE_64)) - output = make([]byte, base64.StdEncoding.EncodedLen(len(input))) - base64.StdEncoding.Encode(output, input) - return - - case util.OBJECT_ENCODING_HEX: - l.Info(fmt.Sprintf("Doing : %s", util.OBJECT_ENCODING_HEX)) - output = make([]byte, hex.EncodedLen(len(input))) - hex.Encode(output, input) - return - - case util.OBJECT_ENCODING_UTF_8: - l.Info(fmt.Sprintf("Doing : %s", util.OBJECT_ENCODING_UTF_8)) - output = input return default: - return nil, fmt.Errorf("error in encode : %s is not supported", objectEncodingFormat) + err = fmt.Errorf("Only pem and pfx 'objectFormat' are supported : %s is not supported", strings.ToLower(cfg.Parameters.ObjectFormat)) + return } } diff --git a/internal/util/util.go b/internal/util/util.go index ec9d266..a1351f8 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -2,14 +2,19 @@ package util import ( "crypto/md5" + "encoding/base64" "encoding/hex" + "fmt" "math/rand" "time" + + "github.com/hashicorp/go-hclog" ) const ( OBJECT_FORMAT_PEM = "pem" OBJECT_FORMAT_PFX = "pfx" + OBJECT_FORMAT_JKS = "jks" OBJECT_ENCODING_UTF_8 = "utf-8" OBJECT_ENCODING_HEX = "hex" @@ -33,3 +38,30 @@ func GetRandomString() string { } return string(contents) } + +func Encode(input []byte, objectEncodingFormat string, l hclog.Logger) (output []byte, err error) { + l.Debug("Starting encode") + + switch objectEncodingFormat { + + case OBJECT_ENCODING_BASE_64: + l.Info(fmt.Sprintf("Doing : %s", OBJECT_ENCODING_BASE_64)) + output = make([]byte, base64.StdEncoding.EncodedLen(len(input))) + base64.StdEncoding.Encode(output, input) + return + + case OBJECT_ENCODING_HEX: + l.Info(fmt.Sprintf("Doing : %s", OBJECT_ENCODING_HEX)) + output = make([]byte, hex.EncodedLen(len(input))) + hex.Encode(output, input) + return + + case OBJECT_ENCODING_UTF_8: + l.Info(fmt.Sprintf("Doing : %s", OBJECT_ENCODING_UTF_8)) + output = input + return + + default: + return nil, fmt.Errorf("error in encode : %s is not supported", objectEncodingFormat) + } +}