Skip to content

Commit

Permalink
[FEATURE] - Additional Controller Secrets
Browse files Browse the repository at this point in the history
Currently unless you override the template there is no way of the platform team getting
additional secrets in the execution of the terraform jobs. With this PR we've added
a command line options --additional-secret which is always added into the executor
terraform container.
  • Loading branch information
gambol99 committed Jul 3, 2022
1 parent 48960b0 commit 6dd891a
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 7 deletions.
1 change: 1 addition & 0 deletions cmd/controller/main.go
Expand Up @@ -64,6 +64,7 @@ func main() {
flags.IntVar(&config.APIServerPort, "apiserver-port", 10080, "The port the apiserver should be listening on")
flags.IntVar(&config.MetricsPort, "metrics-port", 9090, "The port the metric endpoint binds to")
flags.IntVar(&config.WebhookPort, "webhooks-port", 10081, "The port the webhook endpoint binds to")
flags.StringSliceVar(&config.ExecutorSecrets, "executor-secret", []string{}, "Name of a secret in controller namespace which should be added to the job")
flags.StringVar(&config.ExecutorImage, "executor-image", "ghcr.io/appvia/terraform-executor:latest", "The image to use for the executor")
flags.StringVar(&config.InfracostsImage, "infracost-image", "infracosts/infracost:latest", "The image to use for the infracosts")
flags.StringVar(&config.InfracostsSecretName, "cost-secret", "", "Name of the secret on the controller namespace containing your infracost token")
Expand Down
7 changes: 6 additions & 1 deletion pkg/assets/job.yaml.tpl
Expand Up @@ -159,11 +159,16 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
{{- if eq .Provider.Source "secret" }}
envFrom:
{{- if eq .Provider.Source "secret" }}
- secretRef:
name: {{ .Provider.SecretRef.Name }}
{{- end }}
{{- range .ExecutorSecrets }}
- secretRef:
name: {{ . }}
optional: true
{{- end }}
resources:
limits:
cpu: 1
Expand Down
15 changes: 10 additions & 5 deletions pkg/controller/configuration/controller.go
Expand Up @@ -60,6 +60,10 @@ type Controller struct {
cache *cache.Cache
// recorder is the kubernetes event recorder
recorder record.EventRecorder
// ExecutorSecrets is a collection of secrets which should be added to the
// executors job everytime - these are configured by the platform team on the
// cli options
ExecutorSecrets []string
// ControllerNamespace is the namespace where the runner is running
ControllerNamespace string
// EnableInfracosts enables the cost analytics via infracost
Expand All @@ -85,11 +89,12 @@ type Controller struct {
// Add is called to setup the manager for the controller
func (c *Controller) Add(mgr manager.Manager) error {
log.WithFields(log.Fields{
"enable_costs": c.EnableInfracosts,
"enable_watchers": c.EnableWatchers,
"namespace": c.ControllerNamespace,
"policy_image": c.PolicyImage,
"terraform_image": c.TerraformImage,
"additional_secrets": len(c.ExecutorSecrets),
"enable_costs": c.EnableInfracosts,
"enable_watchers": c.EnableWatchers,
"namespace": c.ControllerNamespace,
"policy_image": c.PolicyImage,
"terraform_image": c.TerraformImage,
}).Info("adding the configuration controller")

switch {
Expand Down
1 change: 1 addition & 0 deletions pkg/controller/configuration/delete.go
Expand Up @@ -77,6 +77,7 @@ func (c *Controller) ensureTerraformDestroy(configuration *terraformv1alphav1.Co
runner, err := batch.NewTerraformDestroy(jobs.Options{
EnableInfraCosts: c.EnableInfracosts,
ExecutorImage: c.ExecutorImage,
ExecutorSecrets: c.ExecutorSecrets,
InfracostsImage: c.InfracostsImage,
InfracostsSecret: c.InfracostsSecretName,
Namespace: c.ControllerNamespace,
Expand Down
4 changes: 3 additions & 1 deletion pkg/controller/configuration/ensure.go
Expand Up @@ -457,11 +457,12 @@ func (c *Controller) ensureTerraformPlan(configuration *terraformv1alphav1.Confi
AdditionalLabels: map[string]string{terraformv1alphav1.DriftAnnotation: configuration.GetAnnotations()[terraformv1alphav1.DriftAnnotation]},
EnableInfraCosts: c.EnableInfracosts,
ExecutorImage: c.ExecutorImage,
ExecutorSecrets: c.ExecutorSecrets,
InfracostsImage: c.InfracostsImage,
InfracostsSecret: c.InfracostsSecretName,
Namespace: c.ControllerNamespace,
PolicyImage: c.PolicyImage,
PolicyConstraint: state.checkovConstraint,
PolicyImage: c.PolicyImage,
Template: state.jobTemplate,
TerraformImage: GetTerraformImage(configuration, c.TerraformImage),
}
Expand Down Expand Up @@ -820,6 +821,7 @@ func (c *Controller) ensureTerraformApply(configuration *terraformv1alphav1.Conf
runner, err := jobs.New(configuration, state.provider).NewTerraformApply(jobs.Options{
EnableInfraCosts: c.EnableInfracosts,
ExecutorImage: c.ExecutorImage,
ExecutorSecrets: c.ExecutorSecrets,
InfracostsImage: c.InfracostsImage,
InfracostsSecret: c.InfracostsSecretName,
Namespace: c.ControllerNamespace,
Expand Down
51 changes: 51 additions & 0 deletions pkg/controller/configuration/reconcile_test.go
Expand Up @@ -874,6 +874,57 @@ var _ = Describe("Configuration Controller", func() {
})
})

// ADDITIONAL SECRETS
When("the controller has been configured with additional secrets", func() {
BeforeEach(func() {
configuration = fixtures.NewValidBucketConfiguration(cfgNamespace, "bucket")
Setup(configuration)

ctrl.ExecutorSecrets = []string{"secret1", "secret2"}
result, _, rerr = controllertests.Roll(context.TODO(), ctrl, configuration, 3)
})

It("should have the conditions", func() {
Expect(cc.Get(context.TODO(), configuration.GetNamespacedName(), configuration)).ToNot(HaveOccurred())
Expect(configuration.Status.Conditions).To(HaveLen(defaultConditions))
})

It("should indicate the failure on the conditions", func() {
Expect(cc.Get(context.TODO(), configuration.GetNamespacedName(), configuration)).ToNot(HaveOccurred())

cond := configuration.Status.GetCondition(terraformv1alphav1.ConditionProviderReady)
Expect(cond.Status).To(Equal(metav1.ConditionTrue))
Expect(cond.Reason).To(Equal(corev1alphav1.ReasonReady))
Expect(cond.Message).To(Equal("Provider ready"))
})

It("should have create a plan", func() {
list := &batchv1.JobList{}

Expect(cc.List(context.TODO(), list, client.InNamespace(ctrl.ControllerNamespace))).ToNot(HaveOccurred())
Expect(len(list.Items)).To(Equal(1))
})

It("should have the additional secrets added", func() {
list := &batchv1.JobList{}
Expect(cc.List(context.TODO(), list, client.InNamespace(ctrl.ControllerNamespace))).ToNot(HaveOccurred())
Expect(len(list.Items)).To(Equal(1))

job := list.Items[0]
Expect(job.Spec.Template.Spec.Containers).To(HaveLen(1))
Expect(job.Spec.Template.Spec.Containers[0].EnvFrom).To(HaveLen(3))
Expect(job.Spec.Template.Spec.Containers[0].EnvFrom[0].SecretRef.Name).To(Equal("aws"))

Expect(job.Spec.Template.Spec.Containers[0].EnvFrom[1].SecretRef.Name).To(Equal("secret1"))
Expect(job.Spec.Template.Spec.Containers[0].EnvFrom[1].SecretRef.Optional).ToNot(BeNil())
Expect(*job.Spec.Template.Spec.Containers[0].EnvFrom[1].SecretRef.Optional).To(BeTrue())

Expect(job.Spec.Template.Spec.Containers[0].EnvFrom[2].SecretRef.Name).To(Equal("secret2"))
Expect(job.Spec.Template.Spec.Containers[0].EnvFrom[2].SecretRef.Optional).ToNot(BeNil())
Expect(*job.Spec.Template.Spec.Containers[0].EnvFrom[2].SecretRef.Optional).To(BeTrue())
})
})

When("configuration has not yet run the terraform plan", func() {
BeforeEach(func() {
configuration = fixtures.NewValidBucketConfiguration(cfgNamespace, "bucket")
Expand Down
1 change: 1 addition & 0 deletions pkg/server/server.go
Expand Up @@ -147,6 +147,7 @@ func New(cfg *rest.Config, config Config) (*Server, error) {
EnableTerraformVersions: config.EnableTerraformVersions,
EnableWatchers: config.EnableWatchers,
ExecutorImage: config.ExecutorImage,
ExecutorSecrets: config.ExecutorSecrets,
InfracostsImage: config.InfracostsImage,
InfracostsSecretName: config.InfracostsSecretName,
JobTemplate: config.JobTemplate,
Expand Down
2 changes: 2 additions & 0 deletions pkg/server/types.go
Expand Up @@ -21,6 +21,8 @@ import "time"

// Config is the configuration for the controller
type Config struct {
// ExecutorSecrets is a list of additional secrets to be added to the executor
ExecutorSecrets []string
// APIServerPort is the port to listen on
APIServerPort int
// DriftControllerInterval is the interval for the controller to check for drift
Expand Down
3 changes: 3 additions & 0 deletions pkg/utils/jobs/jobs.go
Expand Up @@ -45,6 +45,8 @@ type Options struct {
EnableInfraCosts bool
// ExecutorImage is the image to use for the terraform jobs
ExecutorImage string
// ExecutorSecrets is a list of additional secrets to add to the job
ExecutorSecrets []string
// InfracostsImage is the image to use for infracosts
InfracostsImage string
// InfracostsSecret is the name of the secret contain the infracost token and url
Expand Down Expand Up @@ -190,6 +192,7 @@ func (r *Render) createTerraformFromTemplate(options Options, stage string) (*ba
},
"EnableInfraCosts": options.EnableInfraCosts,
"EnableVariables": r.configuration.HasVariables(),
"ExecutorSecrets": options.ExecutorSecrets,
"ImagePullPolicy": "IfNotPresent",
"Policy": options.PolicyConstraint,
"ServiceAccount": DefaultServiceAccount,
Expand Down

0 comments on commit 6dd891a

Please sign in to comment.