Allowing at-rest encryption when using S3

This change allows the user to specify `-backend-config="encrypt=1"`
to tell S3 to encrypt the data that's in the bucket when using S3
for remote config storage.

The encryption uses "Amazon S3-managed encryption keys" so it should
not require any further user intervention.

A line was added to the unit test just for coverage.
The acceptance test was modified to:
  a) Use encryption
  b) Push some test data up to the bucket created to ensure
     that Amazon accepts the header.
This commit is contained in:
Robin Walsh 2015-06-19 11:33:03 -07:00
parent f045e9e8d1
commit ad17cf55a0
2 changed files with 33 additions and 8 deletions

View File

@ -32,6 +32,12 @@ func s3Factory(conf map[string]string) (Client, error) {
}
}
serverSideEncryption := false
_, ok = conf["encrypt"]
if ok {
serverSideEncryption = true
}
accessKeyId := conf["access_key"]
secretAccessKey := conf["secret_key"]
@ -60,16 +66,18 @@ func s3Factory(conf map[string]string) (Client, error) {
nativeClient := s3.New(awsConfig)
return &S3Client{
nativeClient: nativeClient,
bucketName: bucketName,
keyName: keyName,
nativeClient: nativeClient,
bucketName: bucketName,
keyName: keyName,
serverSideEncryption: serverSideEncryption,
}, nil
}
type S3Client struct {
nativeClient *s3.S3
bucketName string
keyName string
nativeClient *s3.S3
bucketName string
keyName string
serverSideEncryption bool
}
func (c *S3Client) Get() (*Payload, error) {
@ -113,13 +121,20 @@ func (c *S3Client) Put(data []byte) error {
contentType := "application/octet-stream"
contentLength := int64(len(data))
_, err := c.nativeClient.PutObject(&s3.PutObjectInput{
i := &s3.PutObjectInput{
ContentType: &contentType,
ContentLength: &contentLength,
Body: bytes.NewReader(data),
Bucket: &c.bucketName,
Key: &c.keyName,
})
}
if c.serverSideEncryption {
e := "AES256"
i.ServerSideEncryption = &e
}
_, err := c.nativeClient.PutObject(i)
if err == nil {
return nil

View File

@ -28,6 +28,7 @@ func TestS3Factory(t *testing.T) {
config["region"] = "us-west-1"
config["bucket"] = "foo"
config["key"] = "bar"
config["encrypt"] = "1"
// For this test we'll provide the credentials as config. The
// acceptance tests implicitly test passing credentials as
// environment variables.
@ -80,11 +81,13 @@ func TestS3Client(t *testing.T) {
bucketName := fmt.Sprintf("terraform-remote-s3-test-%x", time.Now().Unix())
keyName := "testState"
testData := []byte(`testing data`)
config := make(map[string]string)
config["region"] = regionName
config["bucket"] = bucketName
config["key"] = keyName
config["encrypt"] = "1"
client, err := s3Factory(config)
if err != nil {
@ -105,6 +108,13 @@ func TestS3Client(t *testing.T) {
if err != nil {
t.Skipf("Failed to create test S3 bucket, so skipping")
}
// Ensure we can perform a PUT request with the encryption header
err = s3Client.Put(testData)
if err != nil {
t.Logf("WARNING: Failed to send test data to S3 bucket. (error was %s)", err)
}
defer func() {
deleteBucketReq := &s3.DeleteBucketInput{
Bucket: &bucketName,