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.
This commit is contained in:
James Nugent 2016-12-06 14:24:21 -06:00
parent 54459900c5
commit 3177fc0765
2 changed files with 48 additions and 32 deletions

View File

@ -1,20 +1,18 @@
package aws package aws
import ( import (
"encoding/base64"
"errors" "errors"
"fmt" "fmt"
"log" "log"
"math/rand" "math/rand"
"strings"
"time" "time"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam" "github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/errwrap" "github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/encryption"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/vault/helper/pgpkeys"
) )
func resourceAwsIamUserLoginProfile() *schema.Resource { func resourceAwsIamUserLoginProfile() *schema.Resource {
@ -99,36 +97,19 @@ func generatePassword(length int) string {
return string(result) 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 { func resourceAwsIamUserLoginProfileCreate(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn iamconn := meta.(*AWSClient).iamconn
encryptionKey, err := encryption.RetrieveGPGKey(d.Get("pgp_key").(string))
if err != nil {
return err
}
username := d.Get("user").(string) username := d.Get("user").(string)
passwordResetRequired := d.Get("password_reset_required").(bool) passwordResetRequired := d.Get("password_reset_required").(bool)
passwordLength := d.Get("password_length").(int) passwordLength := d.Get("password_length").(int)
_, err := iamconn.GetLoginProfile(&iam.GetLoginProfileInput{ _, err = iamconn.GetLoginProfile(&iam.GetLoginProfileInput{
UserName: aws.String(username), UserName: aws.String(username),
}) })
if err != nil { 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) initialPassword := generatePassword(passwordLength)
fingerprint, encrypted, err := encryptPassword(initialPassword, pgpKey) fingerprint, encrypted, err := encryption.EncryptValue(encryptionKey, initialPassword, "Password")
if err != nil { if err != nil {
return err return err
} }

View File

@ -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
}