Skip to content

Commit

Permalink
feat: on validate command, validate that all secrets are tagged
Browse files Browse the repository at this point in the history
This loops through all environments defined in the cloud run yaml file.
If it contains secretKeyRef, (i.e referencing a GCP Secret Manager
Secret) it will go through all fields in the Golang Config to find the
matching environment name field.

If that field is not tagged as secret, we return an error.

This is only run on `-validate` but is a breaking change for that command.
  • Loading branch information
quoral committed Aug 20, 2024
1 parent c840bde commit 17dd619
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 20 deletions.
30 changes: 29 additions & 1 deletion cloudconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cloudconfig
import (
"fmt"
"io"
"os"
"text/tabwriter"
)

Expand Down Expand Up @@ -49,9 +50,18 @@ type configSpec struct {
// Load values into the config.
func (c *Config) Load() error {
if c.yamlServiceSpecificationFilename != "" {
if err := setEnvFromYAMLServiceSpecificationFile(c.yamlServiceSpecificationFilename); err != nil {
envs, err := getEnvFromYAMLServiceSpecificationFile(c.yamlServiceSpecificationFilename)
if err != nil {
return err
}
if err := validateEnvSecretTags(envs, c.configSpecs); err != nil {
return err
}
for _, e := range envs {
if err := os.Setenv(e.Name, e.Value); err != nil {
return err
}
}
}
for _, cs := range c.configSpecs {
if err := c.process(cs.fieldSpecs); err != nil {
Expand All @@ -61,6 +71,24 @@ func (c *Config) Load() error {
return nil
}

func validateEnvSecretTags(envs []env, configSpecs []*configSpec) error {
for _, env := range envs {
if env.ValueFrom.SecretKeyRef.Key == "" && env.ValueFrom.SecretKeyRef.Name == "" {
continue
}
for _, spec := range configSpecs {
for _, f := range spec.fieldSpecs {
if f.Key == env.Name {
if !f.Secret {
return fmt.Errorf("field %s does not have the correct secret tag", f.Name)
}
}
}
}
}
return nil
}

// PrintUsage prints usage of the config to the provided io.Writer.
func (c *Config) PrintUsage(w io.Writer) {
tabs := tabwriter.NewWriter(w, 1, 0, 4, ' ', 0)
Expand Down
42 changes: 24 additions & 18 deletions cloudconfig/yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,18 @@ import (
"gopkg.in/yaml.v3"
)

func setEnvFromYAMLServiceSpecificationFile(name string) (err error) {
type env struct {
Name string
Value string
ValueFrom struct {
SecretKeyRef struct {
Key string
Name string
} `yaml:"secretKeyRef"`
} `yaml:"valueFrom"`
}

func getEnvFromYAMLServiceSpecificationFile(name string) (envValues []env, err error) {
defer func() {
if err != nil {
err = fmt.Errorf("set env from YAML service/job specification file %s: %w", name, err)
Expand All @@ -17,16 +28,12 @@ func setEnvFromYAMLServiceSpecificationFile(name string) (err error) {
var kind struct {
Kind string
}
type env struct {
Name string
Value string
}
data, err := os.ReadFile(name)
if err != nil {
return err
return nil, err
}
if err := yaml.NewDecoder(bytes.NewReader(data)).Decode(&kind); err != nil {
return err
return nil, err
}
var envs []env
switch kind.Kind {
Expand All @@ -46,15 +53,15 @@ func setEnvFromYAMLServiceSpecificationFile(name string) (err error) {
}
}
if err := yaml.NewDecoder(bytes.NewReader(data)).Decode(&config); err != nil {
return err
return nil, err
}
containers := config.Spec.Template.Spec.Containers
if len(containers) == 0 || len(containers) > 10 {
return fmt.Errorf("unexpected number of containers: %d", len(containers))
return nil, fmt.Errorf("unexpected number of containers: %d", len(containers))
}
if config.Metadata.Name != "" {
if err := os.Setenv("K_SERVICE", config.Metadata.Name); err != nil {
return err
return nil, err
}
}
envs = containers[0].Env
Expand All @@ -78,28 +85,27 @@ func setEnvFromYAMLServiceSpecificationFile(name string) (err error) {
}
}
if err := yaml.NewDecoder(bytes.NewReader(data)).Decode(&config); err != nil {
return err
return nil, err
}
containers := config.Spec.Template.Spec.Template.Spec.Containers
if len(containers) == 0 || len(containers) > 10 {
return fmt.Errorf("unexpected number of containers: %d", len(containers))
return nil, fmt.Errorf("unexpected number of containers: %d", len(containers))
}
if config.Metadata.Name != "" {
if err := os.Setenv("K_SERVICE", config.Metadata.Name); err != nil {
return err
return nil, err
}
}
envs = containers[0].Env
default:
return fmt.Errorf("unknown config kind: %s", kind.Kind)
return nil, fmt.Errorf("unknown config kind: %s", kind.Kind)
}
envValues = make([]env, 0, len(envs))
for _, env := range envs {
// Prefer variables from local environment.
if _, ok := os.LookupEnv(env.Name); !ok {
if err := os.Setenv(env.Name, env.Value); err != nil {
return err
}
envValues = append(envValues, env)
}
}
return nil
return envValues, nil
}
5 changes: 4 additions & 1 deletion run.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ func Run(fn func(context.Context) error, options ...Option) (err error) {
)
}
if *validate {
run.configOptions = append(run.configOptions, cloudconfig.WithOptionalSecrets())
run.configOptions = append(
run.configOptions,
cloudconfig.WithOptionalSecrets(),
)
}
config, err := cloudconfig.New("cloudrunner", &run.config, run.configOptions...)
if err != nil {
Expand Down

0 comments on commit 17dd619

Please sign in to comment.