Browse Source

refactoring to implement changes suggested in pull request 265 ,namely, 1) fetch client certificate and key as tls k8s secrets and 2) pass them directly to TLSClientConfig avoiding storing in disk

ric 4 years ago
parent
commit
44ef7756ef

+ 1 - 1
apis/externalsecrets/v1alpha1/secretstore_vault_types.go

@@ -173,7 +173,7 @@ type VaultCertAuth struct {
 	// ClientCert is a certificate to authenticate using the Cert Vault
 	// authentication method
 	// +optional
-	ClientCert string `json:"clientCert"`
+	ClientCert esmeta.SecretKeySelector `json:"clientCert,omitempty"`
 
 	// SecretRef to a key in a Secret resource containing client private key to
 	// authenticate with Vault using the Cert authentication method

+ 1 - 0
apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go

@@ -828,6 +828,7 @@ func (in *VaultAuth) DeepCopy() *VaultAuth {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *VaultCertAuth) DeepCopyInto(out *VaultCertAuth) {
 	*out = *in
+	in.ClientCert.DeepCopyInto(&out.ClientCert)
 	in.SecretRef.DeepCopyInto(&out.SecretRef)
 }
 

+ 20 - 1
deploy/crds/external-secrets.io_clustersecretstores.yaml

@@ -349,7 +349,26 @@ spec:
                               clientCert:
                                 description: ClientCert is a certificate to authenticate
                                   using the Cert Vault authentication method
-                                type: string
+                                properties:
+                                  key:
+                                    description: The key of the entry in the Secret
+                                      resource's `data` field to be used. Some instances
+                                      of this field may be defaulted, in others it
+                                      may be required.
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    type: string
+                                  namespace:
+                                    description: Namespace of the resource being referred
+                                      to. Ignored if referent is not cluster-scoped.
+                                      cluster-scoped defaults to the namespace of
+                                      the referent.
+                                    type: string
+                                required:
+                                - name
+                                type: object
                               secretRef:
                                 description: SecretRef to a key in a Secret resource
                                   containing client private key to authenticate with

+ 20 - 1
deploy/crds/external-secrets.io_secretstores.yaml

@@ -349,7 +349,26 @@ spec:
                               clientCert:
                                 description: ClientCert is a certificate to authenticate
                                   using the Cert Vault authentication method
-                                type: string
+                                properties:
+                                  key:
+                                    description: The key of the entry in the Secret
+                                      resource's `data` field to be used. Some instances
+                                      of this field may be defaulted, in others it
+                                      may be required.
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    type: string
+                                  namespace:
+                                    description: Namespace of the resource being referred
+                                      to. Ignored if referent is not cluster-scoped.
+                                      cluster-scoped defaults to the namespace of
+                                      the referent.
+                                    type: string
+                                required:
+                                - name
+                                type: object
                               secretRef:
                                 description: SecretRef to a key in a Secret resource
                                   containing client private key to authenticate with

+ 8 - 63
pkg/provider/vault/vault.go

@@ -16,8 +16,8 @@ package vault
 
 import (
 	"context"
+	"crypto/tls"
 	"crypto/x509"
-	b64 "encoding/base64"
 	"errors"
 	"fmt"
 	"io/ioutil"
@@ -45,7 +45,6 @@ var (
 
 const (
 	serviceAccTokenPath = "/var/run/secrets/kubernetes.io/serviceaccount/token"
-	certsBasePath = "/auth-certs/"
 
 	errVaultStore     = "received invalid Vault SecretStore resource: %w"
 	errVaultClient    = "cannot setup new vault client: %w"
@@ -350,7 +349,6 @@ func (v *client) secretKeyRef(ctx context.Context, secretRef *esmeta.SecretKeySe
 	}
 
 	value := string(keyBytes)
-
 	valueStr := strings.TrimSpace(value)
 	return valueStr, nil
 }
@@ -523,7 +521,7 @@ func (v *client) requestTokenWithJwtAuth(ctx context.Context, client Client, jwt
 		"role": role,
 		"jwt":  jwt,
 	}
-	url := strings.Join([]string{"/v1", "auth", "cert", "login"}, "/")
+	url := strings.Join([]string{"/v1", "auth", "jwt", "login"}, "/")
 	request := client.NewRequest("POST", url)
 
 	err = request.SetJSONBody(parameters)
@@ -558,26 +556,14 @@ func (v *client) requestTokenWithCertAuth(ctx context.Context, client Client, ce
 		return "", err
 	}
 
-	clientKeyPath, err := getCertPath(clientKey, "client.key")
-	if err != nil {
-		return "", fmt.Errorf(errGetCertPath, err)
-	}
-
-	clientCertPath, err := getCertPath(certAuth.ClientCert, "client.crt")
+	clientCert, err := v.secretKeyRef(ctx, &certAuth.ClientCert)
 	if err != nil {
-		return "", fmt.Errorf(errGetCertPath, err)
-	}
-
-
-	tlscfg := vault.TLSConfig{
-		ClientCert: clientCertPath,
-		ClientKey:  clientKeyPath,
+		return "", err
 	}
 
-	err = cfg.ConfigureTLS(&tlscfg)
-
-	if err != nil {
-		return "", fmt.Errorf(errVaultCert, err)
+	cert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey))
+	if transport, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
+		transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
 	}
 
 	url := strings.Join([]string{"/v1", "auth", "cert", "login"}, "/")
@@ -601,45 +587,4 @@ func (v *client) requestTokenWithCertAuth(ctx context.Context, client Client, ce
 	}
 
 	return token, nil
-}
-
-func getCertPath(cert, filename string) (string, error) {
-
-	certPath := certsBasePath + filename
-
-	if _, err := os.Stat(certsBasePath); os.IsNotExist(err) {
-		_, err := MkdirToStoreCertificate(certsBasePath)
-		return "", err
-	}
-
-	f, err := os.Create(certPath)
-	if err != nil {
-		return "", fmt.Errorf(errOsCreateFile, err)
-	}
-
-	defer f.Close()
-
-	if filename == "client.crt" || filename == "ca.crt" {
-
-		decodedCert, err := b64.StdEncoding.DecodeString(cert)
-		if err != nil {
-			return "", fmt.Errorf(errCertDecode, err)
-		}
-		cert = string(decodedCert)
-	}
-	_, err = f.WriteString(cert)
-	if err != nil {
-		return "", fmt.Errorf(errWriteCertToFile, err)
-	}
-
-	return certPath, nil
-}
-
-func MkdirToStoreCertificate(clientCertsBasePath string) (string, error) {
-
-	if err := os.MkdirAll(clientCertsBasePath, 0700); err != nil {
-		return "", fmt.Errorf(errCertMkdir, err)
-	}
-
-	return "", nil
-}
+}