Wilken Rivera bbb6754367 Fix issue with AWS secrets manager override default stage
Before change
```
⇶  packer build amazon-ebs_secretsmanager_shell-local.json
Error:
template: root:1:3: executing "root" at <aws_secretsmanager `packer/test/keys`

`shell`>: error calling aws_secretsmanager: ResourceNotFoundException: Secrets
Manager can't find the specified secret value for staging label: shell

2020/10/30 12:53:40 [INFO] (telemetry) Finalizing.
template: root:1:3: executing "root" at <aws_secretsmanager `packer/test/keys`
`shell`>: error calling aws_secretsmanager: ResourceNotFoundException: Secrets
Manager can't find the specified secret value for staging label: shell

⇶  packer build amazon-ebs_secretsmanager_shell-local.json.pkr.hcl
Error: Error in function call

  on amazon-ebs_secretsmanager_shell-local.json.pkr.hcl line 28:
  (source code not available)

Call to function "aws_secretsmanager" failed: ResourceNotFoundException: Secrets
Manager can't find the specified secret value for staging label: home.

```

After change
```
⇶  packer.test build amazon-ebs_secretsmanager_shell-local.json
null: output will be in this color.

==> null: Running local shell script: /tmp/packer-shell463393820
    null: boo
    null: keys:powershell
Build 'null' finished after 8 milliseconds 225 microseconds.

==> Wait completed after 8 milliseconds 319 microseconds

==> Builds finished. The artifacts of successful builds are:
--> null: Did not export anything. This is the null builder

⇶  packer.test build amazon-ebs_secretsmanager_shell-local.json.pkr.hcl
null.autogenerated_1: output will be in this color.

==> null.autogenerated_1: Running local shell script: /tmp/packer-shell834410761
    null.autogenerated_1: boo
    null.autogenerated_1: keys:powershell
Build 'null.autogenerated_1' finished after 18 milliseconds 834 microseconds.

==> Wait completed after 18 milliseconds 954 microseconds

==> Builds finished. The artifacts of successful builds are:
--> null.autogenerated_1: Did not export anything. This is the null builder

```
2020-10-30 13:17:38 -04:00

109 lines
2.4 KiB
Go

// Package secretsmanager provide methods to get data from
// AWS Secret Manager
package secretsmanager
import (
"encoding/json"
"errors"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/secretsmanager"
"github.com/aws/aws-sdk-go/service/secretsmanager/secretsmanageriface"
)
// Client represents an AWS Secrets Manager client
type Client struct {
config *AWSConfig
api secretsmanageriface.SecretsManagerAPI
}
// New creates an AWS Session Manager Client
func New(config *AWSConfig) *Client {
c := &Client{
config: config,
}
s := c.newSession(config)
c.api = secretsmanager.New(s)
return c
}
func (c *Client) newSession(config *AWSConfig) *session.Session {
// Initialize config with error verbosity
sessConfig := aws.NewConfig().WithCredentialsChainVerboseErrors(true)
if config.Region != "" {
sessConfig = sessConfig.WithRegion(config.Region)
}
opts := session.Options{
SharedConfigState: session.SharedConfigEnable,
Config: *sessConfig,
}
return session.Must(session.NewSessionWithOptions(opts))
}
// GetSecret return an AWS Secret Manager secret
// in plain text from a given secret name
func (c *Client) GetSecret(spec *SecretSpec) (string, error) {
params := &secretsmanager.GetSecretValueInput{
SecretId: aws.String(spec.Name),
VersionStage: aws.String("AWSCURRENT"),
}
resp, err := c.api.GetSecretValue(params)
if err != nil {
return "", err
}
if resp.SecretString == nil {
return "", errors.New("Secret is not string")
}
secret := SecretString{
Name: *resp.Name,
SecretString: *resp.SecretString,
}
value, err := getSecretValue(&secret, spec)
if err != nil {
return "", err
}
return value, nil
}
func getSecretValue(s *SecretString, spec *SecretSpec) (string, error) {
var secretValue map[string]string
blob := []byte(s.SecretString)
//For those plaintext secrets just return the value
if json.Valid(blob) != true {
return s.SecretString, nil
}
err := json.Unmarshal(blob, &secretValue)
if err != nil {
return "", err
}
// If key is not set and secret has multiple keys, return error
if spec.Key == "" && len(secretValue) > 1 {
return "", errors.New("Secret has multiple values and no key was set")
}
if spec.Key == "" {
for _, v := range secretValue {
return v, nil
}
}
if v, ok := secretValue[spec.Key]; ok {
return v, nil
}
return "", fmt.Errorf("No secret found for key %q", spec.Key)
}