Skip to content
This repository was archived by the owner on Apr 4, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const cfgSecretThreshold = "secret-threshold"

const cfgMode = "mode"
const cfgModeValueAWSKMSSSM = "aws-kms-ssm"
const cfgModeValueAWSParameterStore = "aws-param"

const cfgModeValueGoogleCloudKMSGCS = "google-cloud-kms-gcs"

const cfgGoogleCloudKMSProject = "google-cloud-kms-project"
Expand Down Expand Up @@ -75,7 +77,7 @@ func init() {
configStringVar(
cfgMode,
cfgModeValueGoogleCloudKMSGCS,
fmt.Sprintf("Select the mode to use '%s' => Google Cloud Storage with encryption using Google KMS; '%s' => AWS SSM parameter store using AWS KMS encryption", cfgModeValueGoogleCloudKMSGCS, cfgModeValueAWSKMSSSM),
fmt.Sprintf("Select the mode to use '%s' => Google Cloud Storage with encryption using Google KMS; '%s' => AWS SSM parameter store using AWS KMS encryption; '%s' => AWS Parameter Store with encryption", cfgModeValueGoogleCloudKMSGCS, cfgModeValueAWSKMSSSM, cfgModeValueAWSParameterStore),
)

// Secret config
Expand Down
11 changes: 11 additions & 0 deletions cmd/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/jetstack-experimental/vault-unsealer/pkg/kv"
"github.com/jetstack-experimental/vault-unsealer/pkg/kv/aws_kms"
"github.com/jetstack-experimental/vault-unsealer/pkg/kv/aws_ssm"
"github.com/jetstack-experimental/vault-unsealer/pkg/kv/aws_param"
"github.com/jetstack-experimental/vault-unsealer/pkg/kv/cloudkms"
"github.com/jetstack-experimental/vault-unsealer/pkg/kv/gcs"

Expand Down Expand Up @@ -70,5 +71,15 @@ func kvStoreForConfig(cfg *viper.Viper) (kv.Service, error) {
return kms, nil
}

if cfg.GetString(cfgMode) == cfgModeValueAWSParameterStore {
ssm, err := aws_param.New(cfg.GetString(cfgAWSKMSKeyID), cfg.GetString(cfgAWSSSMKeyPrefix))
if err != nil {
return nil, fmt.Errorf("error creating AWS Parameter Store", err.Error())
}

return ssm, nil
}


return nil, fmt.Errorf("Unsupported backend mode: '%s'", cfg.GetString(cfgMode))
}
88 changes: 88 additions & 0 deletions pkg/kv/aws_param/aws_param.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package aws_param

import (
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ssm"

"github.com/jetstack-experimental/vault-unsealer/pkg/kv"
)

type awsSSM struct {
ssmService *ssm.SSM
kmsKeyId string
keyPrefix string
}

var _ kv.Service = &awsSSM{}
var withDecryption = true;
func NewWithSession(sess *session.Session, kmsKeyId, keyPrefix string) (*awsSSM, error) {
return &awsSSM{
ssmService: ssm.New(sess),
kmsKeyId: kmsKeyId,
keyPrefix: keyPrefix,
}, nil
}

func New(kmsKeyId, keyPrefix string) (*awsSSM, error) {
sess, err := session.NewSession()
if err != nil {
return nil, err
}

return NewWithSession(sess, kmsKeyId, keyPrefix)
}

func newTrue() *bool {
b := true
return &b
}


func (a *awsSSM) Get(key string) ([]byte, error) {
out, err := a.ssmService.GetParameters(&ssm.GetParametersInput{
Names: []*string{
aws.String(a.name(key)),
},
WithDecryption: &withDecryption,
})
if err != nil {
return []byte{}, err
}

if len(out.Parameters) < 1 {
return []byte{}, kv.NewNotFoundError("key '%s' not found")
}

return []byte(*out.Parameters[0].Value), nil
}

func (a *awsSSM) name(key string) string {
return fmt.Sprintf("%s%s", a.keyPrefix, key)
}

func (a *awsSSM) Set(key string, val []byte) error {
_, err := a.ssmService.PutParameter(&ssm.PutParameterInput{
Description: aws.String("vault-unsealer"),
Name: aws.String(a.name(key)),
Overwrite: aws.Bool(true),
Value: aws.String(string(val)),
Type: aws.String("SecureString"),
// KeyId: aws.String(a.kmsKeyId),
})
return err
}

func (a *awsSSM) Delete(key string) error {
_, err := a.ssmService.DeleteParameter(&ssm.DeleteParameterInput{
Name: aws.String(a.name(key)),
})
return err
}

func (g *awsSSM) Test(key string) error {
// TODO: Implement a test if a Set is likely to work, AWS doesn't seemt to provide a dry-run on the parameter store
return nil
}
68 changes: 68 additions & 0 deletions pkg/kv/aws_param/aws_param_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package aws_param

import (
"os"
"testing"

"github.com/jetstack-experimental/vault-unsealer/pkg/kv"
)

func TestAWSIntegration(t *testing.T) {

keyID := os.Getenv("AWS_KMS_KEY_ID")
region := os.Getenv("AWS_REGION")

if keyID == "" {
t.Skip("Skip AWS integration tests: not environment variable 'AWS_KMS_KEY_ID' specified")
}

if region == "" {
t.Skip("Skip AWS integration tests: not environment variable 'AWS_REGION' specified")
}

payloadKey := "test123"
payloadValue := "payload123"

a, err := New(keyID, "test-integration-")
if err != nil {
t.Errorf("Unexpected error creating SSM kv: %s", err)
}

// graceful set (in case it's already existing)
err = a.Set(payloadKey, []byte(payloadValue))
if err != nil {
t.Errorf("Unexpected error storing value in SSM kv: %s", err)
}

// this should also work and overwrite a key
err = a.Set(payloadKey, []byte(payloadValue))
if err != nil {
t.Errorf("Unexpected error storing value in SSM kv: %s", err)
}

// this deletes the key
err = a.Delete(payloadKey)
if err != nil {
t.Errorf("Unexpected error storing value in SSM kv: %s", err)
}

_, err = a.Get(payloadKey)
if _, ok := err.(*kv.NotFoundError); !ok {
t.Errorf("Expected an kv.NotFoundError for a non existing key")
}

err = a.Set(payloadKey, []byte(payloadValue))
if err != nil {
t.Errorf("Unexpected error storing value in SSM kv: %s", err)
}

out, err := a.Get("test123")
if err != nil {
t.Errorf("Unexpected error storing value in SSM kv: %s", err)
}

if exp, act := payloadValue, string(out); exp != act {
t.Errorf("Unexpected decrypt output: exp=%s act=%s", exp, act)
}

}