From 510281c63dc78d35feb6aa87a3d91359c568ead6 Mon Sep 17 00:00:00 2001 From: Robert Bayerl Date: Mon, 7 Nov 2022 14:00:50 -0500 Subject: [PATCH 1/2] add SECRET_PULLER_TYPE to migrate to secret-sidecar --- .../app/models/kubernetes/template_filler.rb | 27 ++++++++++++++++++- .../models/kubernetes/template_filler_test.rb | 22 ++++++++------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/plugins/kubernetes/app/models/kubernetes/template_filler.rb b/plugins/kubernetes/app/models/kubernetes/template_filler.rb index 738ee2ebe4..f5e85784f1 100644 --- a/plugins/kubernetes/app/models/kubernetes/template_filler.rb +++ b/plugins/kubernetes/app/models/kubernetes/template_filler.rb @@ -5,6 +5,7 @@ class TemplateFiller attr_reader :template SECRET_PULLER_IMAGE = ENV['SECRET_PULLER_IMAGE'].presence + SECRET_PULLER_TYPE = ENV.fetch('SECRET_PULLER_TYPE', 'samson_secret_puller') KUBERNETES_ADD_PRESTOP = Samson::EnvCheck.set?('KUBERNETES_ADD_PRESTOP') KUBERNETES_ADD_WELL_KNOWN_LABELS = Samson::EnvCheck.set?('KUBERNETES_ADD_WELL_KNOWN_LABELS') SECRET_PREFIX = "secret/" @@ -298,6 +299,10 @@ def secret_annotations end end + def inject_secret_sidecar? + SECRET_PULLER_TYPE == 'secret-sidecar' + end + # Sets up the secret-puller and the various mounts that are required # if the secret-puller service is enabled # /vaultauth is a secrets volume in the cluster @@ -325,9 +330,28 @@ def set_secret_puller ], resources: { requests: {cpu: "100m", memory: "64Mi"}, - limits: {cpu: "100m", memory: "64Mi"} + limits: {cpu: "100m", memory: "100Mi"} } } + + # Modifies init container to use internal secret-sidecar instead of + # public samson_secret_puller + if inject_secret_sidecar? + container[:command] = '/bin/secret-sidecar-v2' + + container[:volumeMounts] = [ + {moountPath: "/secrets-meta", name: "secrets-meta"}, + {mountPath: "/podinfo", name: "secretkeys"}, + secret_vol + ] + + container[:env] = [ + {name: "VAULT_ADDR", valueFrom: {secretKeyRef: {name: "vaultauth", key: "address"}}}, + {name: "VAULT_ROLE", value: project.permalink}, + {name: "VAULT_TOKEN", valueFrom: {secretKeyRef: {name: "vaultauth", key: "authsecret"}}} + ] + end + init_containers.unshift container # mark the container as not needing a dockerfile @@ -344,6 +368,7 @@ def set_secret_puller volumes = (pod_template[:spec][:volumes] ||= []) volumes.concat [ {name: secret_vol.fetch(:name), emptyDir: {medium: 'Memory'}}, + {name: "secrets-meta", emptyDir: {medium: "Memory"}}, {name: "vaultauth", secret: {secretName: "vaultauth"}}, { name: "secretkeys", diff --git a/plugins/kubernetes/test/models/kubernetes/template_filler_test.rb b/plugins/kubernetes/test/models/kubernetes/template_filler_test.rb index 56fe74c487..299beb00f1 100644 --- a/plugins/kubernetes/test/models/kubernetes/template_filler_test.rb +++ b/plugins/kubernetes/test/models/kubernetes/template_filler_test.rb @@ -609,6 +609,7 @@ def with_init_contnainer_old_syntax(container) around do |test| stub_const Kubernetes::TemplateFiller, :SECRET_PULLER_IMAGE, "docker-registry.example.com/foo:bar", &test + stub_const Kubernetes::TemplateFiller, :SECRET_PULLER_TYPE, "secret-sidecar", &test end before do @@ -622,9 +623,9 @@ def with_init_contnainer_old_syntax(container) init_containers.first[:name].must_equal('secret-puller') init_containers.first[:env].must_equal( [ - {name: "VAULT_TLS_VERIFY", value: "false"}, - {name: "VAULT_MOUNT", value: "secret"}, - {name: "VAULT_PREFIX", value: "apps"} + {name: "VAULT_ADDR", valueFrom: {secretKeyRef: {name: "vaultauth", key: "address"}}}, + {name: "VAULT_ROLE", value: "foo"}, + {name: "VAULT_TOKEN", valueFrom: {secretKeyRef: {name: "vaultauth", key: "authsecret"}}} ] ) @@ -635,11 +636,6 @@ def with_init_contnainer_old_syntax(container) ) end - it "adds vault kv v2 hint so puller knows to use the new api" do - vault_server.update_column :versioned_kv, true - init_containers.first[:env].last.must_equal name: "VAULT_PREFIX", value: "apps" - end - it "fails when vault is not configured" do with_env('SECRET_STORAGE_BACKEND': "Samson::Secrets::HashicorpVaultBackend") do Samson::Secrets::VaultClientManager.instance.expects(:client).raises("Could not find Vault config for pod1") @@ -669,12 +665,12 @@ def with_init_contnainer_old_syntax(container) it "adds to existing volume definitions in the puller" do raw_template[:spec][:template][:spec][:volumes] = [{}] - template.to_hash[:spec][:template][:spec][:volumes].count.must_equal 4 + template.to_hash[:spec][:template][:spec][:volumes].count.must_equal 5 end it "does not duplicate definitions" do raw_template[:spec][:template][:spec][:volumes] = [{name: "vaultauth", secret: {secretName: "vaultauth"}}] - template.to_hash[:spec][:template][:spec][:volumes].count.must_equal 3 + template.to_hash[:spec][:template][:spec][:volumes].count.must_equal 4 end it "adds to existing volume definitions in the primary container" do @@ -704,6 +700,12 @@ def with_init_contnainer_old_syntax(container) e.message.must_include "baz\n (tried: production/foo/pod1/baz" # shows all at once for easier debugging end + describe "container changes for secret sidecar" do + it "sets the init container command" do + init_containers.first[:command].must_equal('/bin/secret-sidecar-v2') + end + end + describe "converting secrets in env to annotations" do def secret_annotations(hash) hash[:spec][:template][:metadata][:annotations].select { |k, _| k.match?("secret") } From 922fc0aa8e9dd02f0a26f6039e9496cab5e3835b Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 7 Nov 2022 17:18:21 -0800 Subject: [PATCH 2/2] fix tests --- .../app/models/kubernetes/template_filler.rb | 27 +++++++++---------- .../models/kubernetes/template_filler_test.rb | 21 ++++++++++----- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/plugins/kubernetes/app/models/kubernetes/template_filler.rb b/plugins/kubernetes/app/models/kubernetes/template_filler.rb index f5e85784f1..db88fb0d03 100644 --- a/plugins/kubernetes/app/models/kubernetes/template_filler.rb +++ b/plugins/kubernetes/app/models/kubernetes/template_filler.rb @@ -299,10 +299,6 @@ def secret_annotations end end - def inject_secret_sidecar? - SECRET_PULLER_TYPE == 'secret-sidecar' - end - # Sets up the secret-puller and the various mounts that are required # if the secret-puller service is enabled # /vaultauth is a secrets volume in the cluster @@ -314,20 +310,10 @@ def set_secret_puller image: SECRET_PULLER_IMAGE, imagePullPolicy: 'IfNotPresent', name: 'secret-puller', - volumeMounts: [ - {mountPath: "/vault-auth", name: "vaultauth"}, - {mountPath: "/secretkeys", name: "secretkeys"}, - secret_vol - ], securityContext: { readOnlyRootFilesystem: true, runAsNonRoot: true }, - env: [ - {name: "VAULT_TLS_VERIFY", value: vault_client.options.fetch(:ssl_verify).to_s}, - {name: "VAULT_MOUNT", value: Samson::Secrets::VaultClientManager::MOUNT}, - {name: "VAULT_PREFIX", value: Samson::Secrets::VaultClientManager::PREFIX} - ], resources: { requests: {cpu: "100m", memory: "64Mi"}, limits: {cpu: "100m", memory: "100Mi"} @@ -336,7 +322,7 @@ def set_secret_puller # Modifies init container to use internal secret-sidecar instead of # public samson_secret_puller - if inject_secret_sidecar? + if SECRET_PULLER_TYPE == 'secret-sidecar' container[:command] = '/bin/secret-sidecar-v2' container[:volumeMounts] = [ @@ -350,6 +336,17 @@ def set_secret_puller {name: "VAULT_ROLE", value: project.permalink}, {name: "VAULT_TOKEN", valueFrom: {secretKeyRef: {name: "vaultauth", key: "authsecret"}}} ] + else + container[:volumeMounts] = [ + {mountPath: "/vault-auth", name: "vaultauth"}, + {mountPath: "/secretkeys", name: "secretkeys"}, + secret_vol + ] + container[:env] = [ + {name: "VAULT_TLS_VERIFY", value: vault_client.options.fetch(:ssl_verify).to_s}, + {name: "VAULT_MOUNT", value: Samson::Secrets::VaultClientManager::MOUNT}, + {name: "VAULT_PREFIX", value: Samson::Secrets::VaultClientManager::PREFIX} + ] end init_containers.unshift container diff --git a/plugins/kubernetes/test/models/kubernetes/template_filler_test.rb b/plugins/kubernetes/test/models/kubernetes/template_filler_test.rb index 299beb00f1..7811a78483 100644 --- a/plugins/kubernetes/test/models/kubernetes/template_filler_test.rb +++ b/plugins/kubernetes/test/models/kubernetes/template_filler_test.rb @@ -609,7 +609,6 @@ def with_init_contnainer_old_syntax(container) around do |test| stub_const Kubernetes::TemplateFiller, :SECRET_PULLER_IMAGE, "docker-registry.example.com/foo:bar", &test - stub_const Kubernetes::TemplateFiller, :SECRET_PULLER_TYPE, "secret-sidecar", &test end before do @@ -623,9 +622,9 @@ def with_init_contnainer_old_syntax(container) init_containers.first[:name].must_equal('secret-puller') init_containers.first[:env].must_equal( [ - {name: "VAULT_ADDR", valueFrom: {secretKeyRef: {name: "vaultauth", key: "address"}}}, - {name: "VAULT_ROLE", value: "foo"}, - {name: "VAULT_TOKEN", valueFrom: {secretKeyRef: {name: "vaultauth", key: "authsecret"}}} + {name: "VAULT_TLS_VERIFY", value: "false"}, + {name: "VAULT_MOUNT", value: "secret"}, + {name: "VAULT_PREFIX", value: "apps"} ] ) @@ -636,6 +635,11 @@ def with_init_contnainer_old_syntax(container) ) end + it "adds vault kv v2 hint so puller knows to use the new api" do + vault_server.update_column :versioned_kv, true + init_containers.first[:env].last.must_equal name: "VAULT_PREFIX", value: "apps" + end + it "fails when vault is not configured" do with_env('SECRET_STORAGE_BACKEND': "Samson::Secrets::HashicorpVaultBackend") do Samson::Secrets::VaultClientManager.instance.expects(:client).raises("Could not find Vault config for pod1") @@ -700,9 +704,14 @@ def with_init_contnainer_old_syntax(container) e.message.must_include "baz\n (tried: production/foo/pod1/baz" # shows all at once for easier debugging end - describe "container changes for secret sidecar" do - it "sets the init container command" do + it "with secret-sidecar" do + stub_const Kubernetes::TemplateFiller, :SECRET_PULLER_TYPE, "secret-sidecar" do init_containers.first[:command].must_equal('/bin/secret-sidecar-v2') + init_containers.first[:env].must_equal [ + {name: "VAULT_ADDR", valueFrom: {secretKeyRef: {name: "vaultauth", key: "address"}}}, + {name: "VAULT_ROLE", value: "foo"}, + {name: "VAULT_TOKEN", valueFrom: {secretKeyRef: {name: "vaultauth", key: "authsecret"}}} + ] end end