Skip to content

Commit

Permalink
CERT-27347 | objectFormat jks support added
Browse files Browse the repository at this point in the history
  • Loading branch information
Gopal Mariyappan committed Sep 8, 2022
1 parent 6440dfa commit 965a6b9
Show file tree
Hide file tree
Showing 9 changed files with 407 additions and 158 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
dist/appviewx-csi-provider
dist/vault-csi-provider
notes
10 changes: 7 additions & 3 deletions dev_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
12 changes: 9 additions & 3 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
178 changes: 178 additions & 0 deletions internal/format/jks.go
Original file line number Diff line number Diff line change
@@ -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
}
131 changes: 131 additions & 0 deletions internal/format/pfx.go
Original file line number Diff line number Diff line change
@@ -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
}
Loading

0 comments on commit 965a6b9

Please sign in to comment.