Skip to content
This repository has been archived by the owner on Nov 11, 2020. It is now read-only.

Commit

Permalink
Merge pull request #29 from jstrachan/changes
Browse files Browse the repository at this point in the history
fix: add verify of secrets
  • Loading branch information
jstrachan authored Mar 10, 2020
2 parents 810f8ca + 486ac41 commit 6c10911
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 6 deletions.
2 changes: 1 addition & 1 deletion pkg/cmd/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type CreateOptions struct {
Args []string
}

// NewCmdCreate creates a command object for the "create" command
// NewCmdCreate creates a command object for the command
func NewCmdCreate() (*cobra.Command, *CreateOptions) {
o := &CreateOptions{}

Expand Down
4 changes: 4 additions & 0 deletions pkg/cmd/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ func (o *RunOptions) verifyBootSecret(requirements *config.RequirementsConfig) e
data := secret.Data[key]
if len(data) > 0 {
found = true
err := secretmgr.VerifyBootSecrets(string(data))
if err != nil {
return errors.Wrapf(err, "invalid secrets yaml in kubernetes secret %s in namespace %s. Please run 'jxl boot secrets edit' to populate them", name, ns)
}
}
}
if !found {
Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/secrets/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ func NewCmdSecrets() *cobra.Command {
},
}
command.AddCommand(common.SplitCommand(NewCmdEdit()))
command.AddCommand(common.SplitCommand(NewCmdImport()))
command.AddCommand(common.SplitCommand(NewCmdExport()))
command.AddCommand(common.SplitCommand(NewCmdImport()))
command.AddCommand(common.SplitCommand(NewCmdVerify()))
return command
}
2 changes: 1 addition & 1 deletion pkg/cmd/secrets/secrets_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type ExportOptions struct {
Console bool
}

// NewCmdExport creates a command object for the "create" command
// NewCmdExport creates a command object for the command
func NewCmdExport() (*cobra.Command, *ExportOptions) {
o := &ExportOptions{}

Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/secrets/secrets_import.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ type ImportOptions struct {
File string
}

// NewCmdImport creates a command object for the "create" command
// NewCmdImport creates a command object for the command
func NewCmdImport() (*cobra.Command, *ImportOptions) {
o := &ImportOptions{}

cmd := &cobra.Command{
Use: "import",
Short: "imports the secrets from the local file system",
Short: "Imports the secrets from the local file system",
Long: importLong,
Example: fmt.Sprintf(importExample, common.BinaryName),
Run: func(cmd *cobra.Command, args []string) {
Expand Down
10 changes: 10 additions & 0 deletions pkg/cmd/secrets/secrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func TestImportExportCommands(t *testing.T) {

_, eo := secrets.NewCmdExport()
_, io := secrets.NewCmdImport()
_, vo := secrets.NewCmdVerify()

ns := "jx"
devEnv := kube.CreateDefaultDevEnvironment(ns)
Expand All @@ -51,6 +52,11 @@ func TestImportExportCommands(t *testing.T) {
f := fakejxfactory.NewFakeFactoryWithObjects(nil, jxObjects, ns)
eo.Factory = f
io.Factory = f
vo.Factory = f

err = vo.Run()
require.Errorf(t, err, "should have failed to verify secrets before they are imported")
t.Logf("caught expected error when no secrets yet: %s", err.Error())

fileName := tmpFile.Name()

Expand All @@ -74,4 +80,8 @@ func TestImportExportCommands(t *testing.T) {
require.NoError(t, err, "failed to read the exported secrets file %s", fileName)
actual := string(data)
assert.Equal(t, modifiedYaml, actual, "the re-exported secrets YAML")

err = vo.Run()
require.NoError(t, err, "should not have failed to to verify secrets after they are imported")

}
57 changes: 57 additions & 0 deletions pkg/cmd/secrets/secrets_verify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package secrets

import (
"fmt"

"github.com/jenkins-x-labs/helmboot/pkg/common"
"github.com/jenkins-x-labs/helmboot/pkg/secretmgr/factory"
"github.com/jenkins-x/jx/pkg/cmd/helper"
"github.com/jenkins-x/jx/pkg/cmd/templates"
"github.com/jenkins-x/jx/pkg/log"
"github.com/spf13/cobra"
)

var (
verifyLong = templates.LongDesc(`
Verifies the secrets are populated correctly
`)

verifyExample = templates.Examples(`
# verifies the secrets are setup correctly
%s secrets verify
`)
)

// VerifyOptions the options for viewing running PRs
type VerifyOptions struct {
factory.KindResolver
File string
}

// NewCmdVerify creates a command object for the command
func NewCmdVerify() (*cobra.Command, *VerifyOptions) {
o := &VerifyOptions{}

cmd := &cobra.Command{
Use: "verify",
Short: "Verifies the secrets are populated correctly",
Long: verifyLong,
Example: fmt.Sprintf(verifyExample, common.BinaryName),
Run: func(cmd *cobra.Command, args []string) {
err := o.Run()
helper.CheckErr(err)
},
}
AddKindResolverFlags(cmd, &o.KindResolver)
return cmd, o
}

// Run implements the command
func (o *VerifyOptions) Run() error {
err := o.VerifySecrets()
if err != nil {
return err
}
log.Logger().Infof("secrets are valid")
return nil
}
2 changes: 1 addition & 1 deletion pkg/cmd/step/step_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type StatusOptions struct {
JXFactory jxfactory.Factory
}

// NewCmdStatus creates a command object for the "create" command
// NewCmdStatus creates a command object for the command
func NewCmdStatus() (*cobra.Command, *StatusOptions) {
o := &StatusOptions{}

Expand Down
25 changes: 25 additions & 0 deletions pkg/secretmgr/factory/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package factory

import (
"fmt"
"strings"

"github.com/jenkins-x-labs/helmboot/pkg/reqhelpers"
"github.com/jenkins-x-labs/helmboot/pkg/secretmgr"
Expand Down Expand Up @@ -57,6 +58,30 @@ func (r *KindResolver) CreateSecretManager() (secretmgr.SecretManager, error) {
return NewSecretManager(r.Kind, r.Factory, requirements)
}

// VerifySecrets verifies that the secrets are valid
func (r *KindResolver) VerifySecrets() error {
secretsYAML := ""
sm, err := r.CreateSecretManager()
if err != nil {
return err
}

cb := func(currentYAML string) (string, error) {
secretsYAML = currentYAML
return currentYAML, nil
}
err = sm.UpsertSecrets(cb, secretmgr.DefaultSecretsYaml)
if err != nil {
return errors.Wrapf(err, "failed to load Secrets YAML from secret manager %s", sm.String())
}

secretsYAML = strings.TrimSpace(secretsYAML)
if secretsYAML == "" {
return errors.Errorf("empty secrets YAML")
}
return secretmgr.VerifyBootSecrets(secretsYAML)
}

func (r *KindResolver) resolveKind(requirements *config.RequirementsConfig) (string, error) {
if requirements.Cluster.Provider == cloud.GKE {
// lets check if we have a Local secret otherwise default to Google
Expand Down
35 changes: 35 additions & 0 deletions pkg/secretmgr/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package secretmgr

import (
"github.com/jenkins-x/jx/pkg/util"
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
)

var expectedSecretPaths = []string{
"secrets.adminUser.username",
"secrets.adminUser.password",
"secrets.hmacToken",
"secrets.pipelineUser.username",
"secrets.pipelineUser.email",
"secrets.pipelineUser.token",
}

// VerifyBootSecrets verifies the boot secrets
func VerifyBootSecrets(secretsYAML string) error {
data := map[string]interface{}{}

err := yaml.Unmarshal([]byte(secretsYAML), &data)
if err != nil {
return errors.Wrap(err, "failed to unmarshal secrets YAML")
}

// simple validation for now, using presence of a string value
for _, path := range expectedSecretPaths {
value := util.GetMapValueAsStringViaPath(data, path)
if value == "" {
return errors.Errorf("missing secret entry: %s", path)
}
}
return nil
}

0 comments on commit 6c10911

Please sign in to comment.