From 3177fc0765e9156ca2c786318b8bcfb5a0fb913e Mon Sep 17 00:00:00 2001 From: James Nugent Date: Tue, 6 Dec 2016 14:24:21 -0600 Subject: [PATCH] provider/aws: Extract helper/encryption library This commit extracts the GPG code used for aws_iam_user_login_profile into a library that can be reused for other resources, and updates the call sites appropriately. --- .../resource_aws_iam_user_login_profile.go | 40 ++++--------------- helper/encryption/encryption.go | 40 +++++++++++++++++++ 2 files changed, 48 insertions(+), 32 deletions(-) create mode 100644 helper/encryption/encryption.go diff --git a/builtin/providers/aws/resource_aws_iam_user_login_profile.go b/builtin/providers/aws/resource_aws_iam_user_login_profile.go index dea063a3b..c60b67fee 100644 --- a/builtin/providers/aws/resource_aws_iam_user_login_profile.go +++ b/builtin/providers/aws/resource_aws_iam_user_login_profile.go @@ -1,20 +1,18 @@ package aws import ( - "encoding/base64" "errors" "fmt" "log" "math/rand" - "strings" "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/iam" "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/encryption" "github.com/hashicorp/terraform/helper/schema" - "github.com/hashicorp/vault/helper/pgpkeys" ) func resourceAwsIamUserLoginProfile() *schema.Resource { @@ -99,36 +97,19 @@ func generatePassword(length int) string { return string(result) } -func encryptPassword(password string, pgpKey string) (string, string, error) { - const keybasePrefix = "keybase:" - - encryptionKey := pgpKey - if strings.HasPrefix(pgpKey, keybasePrefix) { - publicKeys, err := pgpkeys.FetchKeybasePubkeys([]string{pgpKey}) - if err != nil { - return "", "", errwrap.Wrapf( - fmt.Sprintf("Error retrieving Public Key for %s: {{err}}", pgpKey), err) - } - encryptionKey = publicKeys[pgpKey] - } - - fingerprints, encrypted, err := pgpkeys.EncryptShares([][]byte{[]byte(password)}, []string{encryptionKey}) - if err != nil { - return "", "", errwrap.Wrapf( - fmt.Sprintf("Error encrypting password for %s: {{err}}", pgpKey), err) - } - - return fingerprints[0], base64.StdEncoding.EncodeToString(encrypted[0]), nil -} - func resourceAwsIamUserLoginProfileCreate(d *schema.ResourceData, meta interface{}) error { iamconn := meta.(*AWSClient).iamconn + encryptionKey, err := encryption.RetrieveGPGKey(d.Get("pgp_key").(string)) + if err != nil { + return err + } + username := d.Get("user").(string) passwordResetRequired := d.Get("password_reset_required").(bool) passwordLength := d.Get("password_length").(int) - _, err := iamconn.GetLoginProfile(&iam.GetLoginProfileInput{ + _, err = iamconn.GetLoginProfile(&iam.GetLoginProfileInput{ UserName: aws.String(username), }) if err != nil { @@ -143,13 +124,8 @@ func resourceAwsIamUserLoginProfileCreate(d *schema.ResourceData, meta interface } } - var pgpKey string - if pgpKeyInterface, ok := d.GetOk("pgp_key"); ok { - pgpKey = pgpKeyInterface.(string) - } - initialPassword := generatePassword(passwordLength) - fingerprint, encrypted, err := encryptPassword(initialPassword, pgpKey) + fingerprint, encrypted, err := encryption.EncryptValue(encryptionKey, initialPassword, "Password") if err != nil { return err } diff --git a/helper/encryption/encryption.go b/helper/encryption/encryption.go new file mode 100644 index 000000000..a565c6dd2 --- /dev/null +++ b/helper/encryption/encryption.go @@ -0,0 +1,40 @@ +package encryption + +import ( + "encoding/base64" + "fmt" + "strings" + + "github.com/hashicorp/errwrap" + "github.com/hashicorp/vault/helper/pgpkeys" +) + +// RetrieveGPGKey returns the PGP key specified as the pgpKey parameter, or queries +// the public key from the keybase service if the parameter is a keybase username +// prefixed with the phrase "keybase:" +func RetrieveGPGKey(pgpKey string) (string, error) { + const keybasePrefix = "keybase:" + + encryptionKey := pgpKey + if strings.HasPrefix(pgpKey, keybasePrefix) { + publicKeys, err := pgpkeys.FetchKeybasePubkeys([]string{pgpKey}) + if err != nil { + return "", errwrap.Wrapf(fmt.Sprintf("Error retrieving Public Key for %s: {{err}}", pgpKey), err) + } + encryptionKey = publicKeys[pgpKey] + } + + return encryptionKey, nil +} + +// EncryptValue encrypts the given value with the given encryption key. Description +// should be set such that errors return a meaningful user-facing response. +func EncryptValue(encryptionKey, value, description string) (string, string, error) { + fingerprints, encryptedValue, err := + pgpkeys.EncryptShares([][]byte{[]byte(value)}, []string{encryptionKey}) + if err != nil { + return "", "", errwrap.Wrapf(fmt.Sprintf("Error encrypting %s: {{err}}", description), err) + } + + return fingerprints[0], base64.StdEncoding.EncodeToString(encryptedValue[0]), nil +}