Skip to content

Commit

Permalink
SyncAll now handleling kubernetes.io/basic-auth secrets
Browse files Browse the repository at this point in the history
  • Loading branch information
manedurphy committed Jul 29, 2021
1 parent ca3d44d commit 7431044
Show file tree
Hide file tree
Showing 11 changed files with 194 additions and 3 deletions.
9 changes: 9 additions & 0 deletions apis/v1alpha1/secretproviderclass_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,22 @@ type SecretObject struct {
SyncAll bool `json:"syncAll,omitempty"`
}

// SyncOptions defines the desired state of synced K8s secret objects and replaces SecretObject
type SyncOptions struct {
// syncs all secrets listed in the parameters field of SecretProviderClass
SyncAll bool `json:"syncAll,omitempty"`
// type of K8s secret object
Type string `json:"type,omitempty"`
}

// SecretProviderClassSpec defines the desired state of SecretProviderClass
type SecretProviderClassSpec struct {
// Configuration for provider name
Provider Provider `json:"provider,omitempty"`
// Configuration for specific provider
Parameters map[string]string `json:"parameters,omitempty"`
SecretObjects []*SecretObject `json:"secretObjects,omitempty"`
SyncOptions SyncOptions `json:"syncOptions,omitempty"`
}

// ByPodStatus defines the state of SecretProviderClass as seen by
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ spec:
provider:
description: Configuration for provider name
type: string
syncOptions:
description: SyncOptions defines the secret type when syncing all secrets listed in the parameters field
properties:
syncAll:
description: SyncAll as true will sync all secrets defined in the parameters field to K8s
type: boolean
type:
description: type of K8s secret object
type: string
type: object
secretObjects:
items:
description: SecretObject defines the desired state of synced K8s secret objects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ spec:
provider:
description: Configuration for provider name
type: string
syncOptions:
description: SyncOptions defines the secret type when syncing all secrets listed in the parameters field
properties:
syncAll:
description: SyncAll as true will sync all secrets defined in the parameters field to K8s
type: boolean
type:
description: type of K8s secret object
type: string
type: object
secretObjects:
items:
description: SecretObject defines the desired state of synced K8s secret objects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ spec:
provider:
description: Configuration for provider name
type: string
syncOptions:
description: SyncOptions defines the secret type when syncing all secrets listed in the parameters field
properties:
syncAll:
description: SyncAll as true will sync all secrets defined in the parameters field to K8s
type: boolean
type:
description: type of K8s secret object
type: string
type: object
secretObjects:
items:
description: SecretObject defines the desired state of synced K8s secret objects
Expand Down
8 changes: 6 additions & 2 deletions controllers/secretproviderclasspodstatus_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ func (r *SecretProviderClassPodStatusReconciler) Reconcile(ctx context.Context,
return ctrl.Result{}, err
}

if len(spc.Spec.SecretObjects) == 0 {
if len(spc.Spec.SecretObjects) == 0 && !spc.Spec.SyncOptions.SyncAll {
klog.InfoS("no secret objects defined for spc, nothing to reconcile", "spc", klog.KObj(spc), "spcps", klog.KObj(spcPodStatus))
return ctrl.Result{}, nil
}
Expand All @@ -285,9 +285,13 @@ func (r *SecretProviderClassPodStatusReconciler) Reconcile(ctx context.Context,

files, err := fileutil.GetMountedFiles(spcPodStatus.Status.TargetPath)

if spc.Spec.SyncOptions.SyncAll {
spc.Spec.SecretObjects = spcutil.BuildSecretObjects(files, spc.Spec.SyncOptions.Type)
}

for _, secretObj := range spc.Spec.SecretObjects {
if secretObj.SyncAll {
if secretutil.GetSecretType(strings.TrimSpace(secretObj.Type)) != corev1.SecretTypeOpaque {
if secretutil.GetSecretType(strings.TrimSpace(secretObj.Type)) != corev1.SecretTypeOpaque && secretutil.GetSecretType(strings.TrimSpace(secretObj.Type)) != corev1.SecretTypeBasicAuth {
return ctrl.Result{}, fmt.Errorf("secret provider class %s/%s cannot use syncAll for non-opaque secrets", spc.Namespace, spc.Name)
}

Expand Down
10 changes: 10 additions & 0 deletions deploy/secrets-store.csi.x-k8s.io_secretproviderclasses.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ spec:
provider:
description: Configuration for provider name
type: string
syncOptions:
description: SyncOptions defines the secret type when syncing all secrets listed in the parameters field
properties:
syncAll:
description: SyncAll as true will sync all secrets defined in the parameters field to K8s
type: boolean
type:
description: type of K8s secret object
type: string
type: object
secretObjects:
items:
description: SecretObject defines the desired state of synced K8s secret objects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ spec:
provider:
description: Configuration for provider name
type: string
syncOptions:
description: SyncOptions defines the secret type when syncing all secrets listed in the parameters field
properties:
syncAll:
description: SyncAll as true will sync all secrets defined in the parameters field to K8s
type: boolean
type:
description: type of K8s secret object
type: string
type: object
secretObjects:
items:
description: SecretObject defines the desired state of synced K8s secret objects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ spec:
provider:
description: Configuration for provider name
type: string
syncOptions:
description: SyncOptions defines the secret type when syncing all secrets listed in the parameters field
properties:
syncAll:
description: SyncAll as true will sync all secrets defined in the parameters field to K8s
type: boolean
type:
description: type of K8s secret object
type: string
type: object
secretObjects:
items:
description: SecretObject defines the desired state of synced K8s secret objects
Expand Down
7 changes: 6 additions & 1 deletion pkg/rotation/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,12 +429,17 @@ func (r *Reconciler) reconcile(ctx context.Context, spcps *v1alpha1.SecretProvid
}
}

if len(spc.Spec.SecretObjects) == 0 {
if len(spc.Spec.SecretObjects) == 0 && !spc.Spec.SyncOptions.SyncAll {
klog.InfoS("spc doesn't contain secret objects", "spc", klog.KObj(spc), "pod", klog.KObj(pod), "controller", "rotation")
return nil
}

files, err := fileutil.GetMountedFiles(spcps.Status.TargetPath)

if spc.Spec.SyncOptions.SyncAll {
spc.Spec.SecretObjects = spcutil.BuildSecretObjects(files, spc.Spec.SyncOptions.Type)
}

for _, secretObj := range spc.Spec.SecretObjects {
if secretObj.SyncAll {
if secretutil.GetSecretType(strings.TrimSpace(secretObj.Type)) != v1.SecretTypeOpaque {
Expand Down
22 changes: 22 additions & 0 deletions pkg/util/secretutil/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,21 @@ func getPrivateKey(data []byte) ([]byte, error) {
return pem.EncodeToMemory(block), nil
}

type basicAuthCreds struct {
Username string
Password string
}

// getCredentials parses the mounted content and returns the required
// key-value pairs for a kubernetes.io/basic-auth K8s secret
func getCredentials(data []byte) basicAuthCreds {
credentials := strings.Split(string(data), ";")
return basicAuthCreds{
Username: credentials[0],
Password: credentials[1],
}
}

// GetSecretType returns a k8s secret type, defaults to Opaque
func GetSecretType(sType string) corev1.SecretType {
switch sType {
Expand Down Expand Up @@ -188,6 +203,13 @@ func GetSecretData(secretObjData []*v1alpha1.SecretObjectData, secretType corev1
}
datamap[dataKey] = c
}
if secretType == corev1.SecretTypeBasicAuth {
credentials := getCredentials(content)
delete(datamap, dataKey)

datamap["username"] = []byte(credentials.Username)
datamap["password"] = []byte(credentials.Password)
}
}
return datamap, nil
}
Expand Down
91 changes: 91 additions & 0 deletions pkg/util/spcutil/secret_object_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,22 @@ package spcutil
import (
"strings"

corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/secrets-store-csi-driver/apis/v1alpha1"
"sigs.k8s.io/secrets-store-csi-driver/pkg/util/secretutil"
)

const (
tlsKey = "tls.key"
tlsCert = "tls.crt"
dockerConfigJsonKey = ".dockerconfigjson"
basicAuthUsername = "username"
basicAuthPassword = "password"
)

// builds the data field of a SecretObject when syncAll is true
func BuildSecretObjectData(files map[string]string, secretObj *v1alpha1.SecretObject) {

for key := range files {
nested := strings.Split(key, "/")
var renamedKey string
Expand All @@ -30,3 +41,83 @@ func BuildSecretObjectData(files map[string]string, secretObj *v1alpha1.SecretOb
})
}
}

func BuildSecretObjects(files map[string]string, secretType string) []*v1alpha1.SecretObject {
secretObjects := []*v1alpha1.SecretObject{}

var secretObject *v1alpha1.SecretObject
for key := range files {

switch {
case secretutil.GetSecretType(strings.TrimSpace(secretType)) == corev1.SecretTypeOpaque:
secretObject = buildOpaqueSecretDataObject(key, secretType)
case secretutil.GetSecretType(strings.TrimSpace(secretType)) == corev1.SecretTypeTLS:
secretObject = buildTLSSecretDataObject(key, secretType)
case secretutil.GetSecretType(strings.TrimSpace(secretType)) == corev1.SecretTypeDockerConfigJson:
secretObject = buildDockerConfigJsonSecretDataObject(key, secretType)
case secretutil.GetSecretType(strings.TrimSpace(secretType)) == corev1.SecretTypeBasicAuth:
secretObject = buildBasicAuthSecretDataObject(key, secretType)
}

secretObjects = append(secretObjects, secretObject)
}

return secretObjects
}

func buildOpaqueSecretDataObject(key string, secretType string) *v1alpha1.SecretObject {
return &v1alpha1.SecretObject{
SecretName: key,
Type: secretType,
Data: []*v1alpha1.SecretObjectData{
{
ObjectName: key,
Key: key,
},
},
}
}

func buildTLSSecretDataObject(key string, secretType string) *v1alpha1.SecretObject {
return &v1alpha1.SecretObject{
SecretName: key,
Type: secretType,
Data: []*v1alpha1.SecretObjectData{
{
ObjectName: key,
Key: tlsKey,
},
{
ObjectName: key,
Key: tlsCert,
},
},
}
}

func buildDockerConfigJsonSecretDataObject(key string, secretType string) *v1alpha1.SecretObject {
return &v1alpha1.SecretObject{
SecretName: key,
Type: secretType,
Data: []*v1alpha1.SecretObjectData{
{
ObjectName: key,
Key: dockerConfigJsonKey,
},
},
}
}

func buildBasicAuthSecretDataObject(key string, secretType string) *v1alpha1.SecretObject {

return &v1alpha1.SecretObject{
SecretName: key,
Type: secretType,
Data: []*v1alpha1.SecretObjectData{
{
ObjectName: key,
Key: key,
},
},
}
}

0 comments on commit 7431044

Please sign in to comment.