From 9b4d8eb29231c0febbbe7e64aa0f5a78c3957aa6 Mon Sep 17 00:00:00 2001 From: Manuel Morejon Date: Fri, 11 Aug 2023 02:29:32 +0200 Subject: [PATCH 1/2] feat: add volumes projected detection Signed-off-by: Manuel Morejon --- pkg/onepassword/deployments_test.go | 20 +++++++++--- pkg/onepassword/object_generators_for_test.go | 23 ++++++++++++++ pkg/onepassword/volumes.go | 31 +++++++++++++++++-- pkg/onepassword/volumes_test.go | 16 ++++++++-- 4 files changed, 80 insertions(+), 10 deletions(-) diff --git a/pkg/onepassword/deployments_test.go b/pkg/onepassword/deployments_test.go index d2879a5..bff478a 100644 --- a/pkg/onepassword/deployments_test.go +++ b/pkg/onepassword/deployments_test.go @@ -9,18 +9,30 @@ import ( func TestIsDeploymentUsingSecretsUsingVolumes(t *testing.T) { secretNamesToSearch := map[string]*corev1.Secret{ - "onepassword-database-secret": {}, - "onepassword-api-key": {}, + "onepassword-database-secret": {}, + "onepassword-api-key": {}, + "onepassword-app-token": {}, + "onepassword-user-credentials": {}, } volumeSecretNames := []string{ "onepassword-database-secret", "onepassword-api-key", - "some_other_key", } + volumes := generateVolumes(volumeSecretNames) + + volumeProjectedSecretNames := []string{ + "onepassword-app-token", + "onepassword-user-credentials", + } + + volumeProjected := generateVolumesProjected(volumeProjectedSecretNames) + + volumes = append(volumes, volumeProjected) + deployment := &appsv1.Deployment{} - deployment.Spec.Template.Spec.Volumes = generateVolumes(volumeSecretNames) + deployment.Spec.Template.Spec.Volumes = volumes if !IsDeploymentUsingSecrets(deployment, secretNamesToSearch) { t.Errorf("Expected that deployment was using secrets but they were not detected.") } diff --git a/pkg/onepassword/object_generators_for_test.go b/pkg/onepassword/object_generators_for_test.go index 2392070..8e95abf 100644 --- a/pkg/onepassword/object_generators_for_test.go +++ b/pkg/onepassword/object_generators_for_test.go @@ -17,6 +17,29 @@ func generateVolumes(names []string) []corev1.Volume { } return volumes } +func generateVolumesProjected(names []string) corev1.Volume { + volumesProjection := []corev1.VolumeProjection{} + for i := 0; i < len(names); i++ { + volumeProjection := corev1.VolumeProjection{ + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: names[i], + }, + }, + } + volumesProjection = append(volumesProjection, volumeProjection) + } + volume := corev1.Volume{ + Name: "someName", + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: volumesProjection, + }, + }, + } + + return volume +} func generateContainersWithSecretRefsFromEnv(names []string) []corev1.Container { containers := []corev1.Container{} for i := 0; i < len(names); i++ { diff --git a/pkg/onepassword/volumes.go b/pkg/onepassword/volumes.go index adf2e8b..ed4e182 100644 --- a/pkg/onepassword/volumes.go +++ b/pkg/onepassword/volumes.go @@ -7,12 +7,26 @@ func AreVolumesUsingSecrets(volumes []corev1.Volume, secrets map[string]*corev1. if secret := volumes[i].Secret; secret != nil { secretName := secret.SecretName _, ok := secrets[secretName] - if ok { - return true + if !ok { + return false + } + } + if volumes[i].Projected != nil { + for j := 0; j < len(volumes[i].Projected.Sources); j++ { + if secret := volumes[i].Projected.Sources[j].Secret; secret != nil { + secretName := secret.Name + _, ok := secrets[secretName] + if !ok { + return false + } + } } } } - return false + if len(volumes) == 0 { + return false + } + return true } func AppendUpdatedVolumeSecrets(volumes []corev1.Volume, secrets map[string]*corev1.Secret, updatedDeploymentSecrets map[string]*corev1.Secret) map[string]*corev1.Secret { @@ -24,6 +38,17 @@ func AppendUpdatedVolumeSecrets(volumes []corev1.Volume, secrets map[string]*cor updatedDeploymentSecrets[secret.Name] = secret } } + if volumes[i].Projected != nil { + for j := 0; j < len(volumes[i].Projected.Sources); j++ { + if secret := volumes[i].Projected.Sources[j].Secret; secret != nil { + secretName := secret.Name + secret, ok := secrets[secretName] + if ok { + updatedDeploymentSecrets[secret.Name] = secret + } + } + } + } } return updatedDeploymentSecrets } diff --git a/pkg/onepassword/volumes_test.go b/pkg/onepassword/volumes_test.go index c00372d..00828e6 100644 --- a/pkg/onepassword/volumes_test.go +++ b/pkg/onepassword/volumes_test.go @@ -8,18 +8,28 @@ import ( func TestAreVolmesUsingSecrets(t *testing.T) { secretNamesToSearch := map[string]*corev1.Secret{ - "onepassword-database-secret": {}, - "onepassword-api-key": {}, + "onepassword-database-secret": {}, + "onepassword-api-key": {}, + "onepassword-app-token": {}, + "onepassword-user-credentials": {}, } volumeSecretNames := []string{ "onepassword-database-secret", "onepassword-api-key", - "some_other_key", } volumes := generateVolumes(volumeSecretNames) + volumeProjectedSecretNames := []string{ + "onepassword-app-token", + "onepassword-user-credentials", + } + + volumeProjected := generateVolumesProjected(volumeProjectedSecretNames) + + volumes = append(volumes, volumeProjected) + if !AreVolumesUsingSecrets(volumes, secretNamesToSearch) { t.Errorf("Expected that volumes were using secrets but they were not detected.") } From 1e73bc12205a793ea77d94ba1092e11d90b5972a Mon Sep 17 00:00:00 2001 From: Manuel Morejon Date: Tue, 15 Aug 2023 01:30:41 +0200 Subject: [PATCH 2/2] refactor volume functions Signed-off-by: Manuel Morejon --- pkg/onepassword/volumes.go | 70 ++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/pkg/onepassword/volumes.go b/pkg/onepassword/volumes.go index ed4e182..cb1c1b1 100644 --- a/pkg/onepassword/volumes.go +++ b/pkg/onepassword/volumes.go @@ -4,23 +4,10 @@ import corev1 "k8s.io/api/core/v1" func AreVolumesUsingSecrets(volumes []corev1.Volume, secrets map[string]*corev1.Secret) bool { for i := 0; i < len(volumes); i++ { - if secret := volumes[i].Secret; secret != nil { - secretName := secret.SecretName - _, ok := secrets[secretName] - if !ok { - return false - } - } - if volumes[i].Projected != nil { - for j := 0; j < len(volumes[i].Projected.Sources); j++ { - if secret := volumes[i].Projected.Sources[j].Secret; secret != nil { - secretName := secret.Name - _, ok := secrets[secretName] - if !ok { - return false - } - } - } + secret := IsVolumeUsingSecret(volumes[i], secrets) + secretProjection := IsVolumeUsingSecretProjection(volumes[i], secrets) + if secret == nil && secretProjection == nil { + return false } } if len(volumes) == 0 { @@ -31,24 +18,41 @@ func AreVolumesUsingSecrets(volumes []corev1.Volume, secrets map[string]*corev1. func AppendUpdatedVolumeSecrets(volumes []corev1.Volume, secrets map[string]*corev1.Secret, updatedDeploymentSecrets map[string]*corev1.Secret) map[string]*corev1.Secret { for i := 0; i < len(volumes); i++ { - if secret := volumes[i].Secret; secret != nil { - secretName := secret.SecretName - secret, ok := secrets[secretName] - if ok { - updatedDeploymentSecrets[secret.Name] = secret - } - } - if volumes[i].Projected != nil { - for j := 0; j < len(volumes[i].Projected.Sources); j++ { - if secret := volumes[i].Projected.Sources[j].Secret; secret != nil { - secretName := secret.Name - secret, ok := secrets[secretName] - if ok { - updatedDeploymentSecrets[secret.Name] = secret - } - } + secret := IsVolumeUsingSecret(volumes[i], secrets) + if secret != nil { + updatedDeploymentSecrets[secret.Name] = secret + } else { + secretProjection := IsVolumeUsingSecretProjection(volumes[i], secrets) + if secretProjection != nil { + updatedDeploymentSecrets[secretProjection.Name] = secretProjection } } } return updatedDeploymentSecrets } + +func IsVolumeUsingSecret(volume corev1.Volume, secrets map[string]*corev1.Secret) *corev1.Secret { + if secret := volume.Secret; secret != nil { + secretName := secret.SecretName + secretFound, ok := secrets[secretName] + if ok { + return secretFound + } + } + return nil +} + +func IsVolumeUsingSecretProjection(volume corev1.Volume, secrets map[string]*corev1.Secret) *corev1.Secret { + if volume.Projected != nil { + for i := 0; i < len(volume.Projected.Sources); i++ { + if secret := volume.Projected.Sources[i].Secret; secret != nil { + secretName := secret.Name + secretFound, ok := secrets[secretName] + if ok { + return secretFound + } + } + } + } + return nil +}