Skip to content

Commit

Permalink
object storage sse support
Browse files Browse the repository at this point in the history
  • Loading branch information
tna0y committed Sep 9, 2020
1 parent 9c8fe68 commit b46be90
Show file tree
Hide file tree
Showing 2 changed files with 240 additions and 0 deletions.
139 changes: 139 additions & 0 deletions yandex/resource_yandex_storage_bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,44 @@ func resourceYandexStorageBucket() *schema.Resource {
Optional: true,
Default: false,
},
"server_side_encryption_configuration": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"rule": {
Type: schema.TypeList,
MaxItems: 1,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"apply_server_side_encryption_by_default": {
Type: schema.TypeList,
MaxItems: 1,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"kms_master_key_id": {
Type: schema.TypeString,
Required: true,
},
"sse_algorithm": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
s3.ServerSideEncryptionAwsKms,
}, false),
},
},
},
},
},
},
},
},
},
},
},
}
}
Expand Down Expand Up @@ -263,6 +301,12 @@ func resourceYandexStorageBucketUpdate(d *schema.ResourceData, meta interface{})
}
}

if d.HasChange("server_side_encryption_configuration") {
if err := resourceAwsS3BucketServerSideEncryptionConfigurationUpdate(s3Client, d); err != nil {
return err
}
}

return resourceYandexStorageBucketRead(d, meta)
}

Expand Down Expand Up @@ -418,6 +462,25 @@ func resourceYandexStorageBucketRead(d *schema.ResourceData, meta interface{}) e
}
}

// Read the bucket server side encryption configuration

encryptionResponse, err := retryFlakyS3Responses(func() (interface{}, error) {
return s3Client.GetBucketEncryption(&s3.GetBucketEncryptionInput{
Bucket: aws.String(d.Id()),
})
})
if err != nil && !isAWSErr(err, "ServerSideEncryptionConfigurationNotFoundError", "encryption configuration was not found") {
return fmt.Errorf("error getting S3 Bucket encryption: %s", err)
}

serverSideEncryptionConfiguration := make([]map[string]interface{}, 0)
if encryption, ok := encryptionResponse.(*s3.GetBucketEncryptionOutput); ok && encryption.ServerSideEncryptionConfiguration != nil {
serverSideEncryptionConfiguration = flattenS3ServerSideEncryptionConfiguration(encryption.ServerSideEncryptionConfiguration)
}
if err := d.Set("server_side_encryption_configuration", serverSideEncryptionConfiguration); err != nil {
return fmt.Errorf("error setting server_side_encryption_configuration: %s", err)
}

return nil
}

Expand Down Expand Up @@ -1010,6 +1073,63 @@ func resourceYandexStorageBucketGrantsUpdate(s3conn *s3.S3, d *schema.ResourceDa
return nil
}

func resourceAwsS3BucketServerSideEncryptionConfigurationUpdate(s3conn *s3.S3, d *schema.ResourceData) error {
bucket := d.Get("bucket").(string)
serverSideEncryptionConfiguration := d.Get("server_side_encryption_configuration").([]interface{})
if len(serverSideEncryptionConfiguration) == 0 {
log.Printf("[DEBUG] Delete server side encryption configuration: %#v", serverSideEncryptionConfiguration)
i := &s3.DeleteBucketEncryptionInput{
Bucket: aws.String(bucket),
}

_, err := s3conn.DeleteBucketEncryption(i)
if err != nil {
return fmt.Errorf("error removing S3 bucket server side encryption: %s", err)
}
return nil
}

c := serverSideEncryptionConfiguration[0].(map[string]interface{})

rc := &s3.ServerSideEncryptionConfiguration{}

rcRules := c["rule"].([]interface{})
var rules []*s3.ServerSideEncryptionRule
for _, v := range rcRules {
rr := v.(map[string]interface{})
rrDefault := rr["apply_server_side_encryption_by_default"].([]interface{})
sseAlgorithm := rrDefault[0].(map[string]interface{})["sse_algorithm"].(string)
kmsMasterKeyId := rrDefault[0].(map[string]interface{})["kms_master_key_id"].(string)
rcDefaultRule := &s3.ServerSideEncryptionByDefault{
SSEAlgorithm: aws.String(sseAlgorithm),
}
if kmsMasterKeyId != "" {
rcDefaultRule.KMSMasterKeyID = aws.String(kmsMasterKeyId)
}
rcRule := &s3.ServerSideEncryptionRule{
ApplyServerSideEncryptionByDefault: rcDefaultRule,
}

rules = append(rules, rcRule)
}

rc.Rules = rules
i := &s3.PutBucketEncryptionInput{
Bucket: aws.String(bucket),
ServerSideEncryptionConfiguration: rc,
}
log.Printf("[DEBUG] S3 put bucket replication configuration: %#v", i)

_, err := retryFlakyS3Responses(func() (interface{}, error) {
return s3conn.PutBucketEncryption(i)
})
if err != nil {
return fmt.Errorf("error putting S3 server side encryption configuration: %s", err)
}

return nil
}

func flattenGrants(ap *s3.GetBucketAclOutput) []interface{} {
//if ACL grants contains bucket owner FULL_CONTROL only - it is default "private" acl
if len(ap.Grants) == 1 && aws.StringValue(ap.Grants[0].Grantee.ID) == aws.StringValue(ap.Owner.ID) &&
Expand Down Expand Up @@ -1050,6 +1170,25 @@ func flattenGrants(ap *s3.GetBucketAclOutput) []interface{} {
return grants
}

func flattenS3ServerSideEncryptionConfiguration(c *s3.ServerSideEncryptionConfiguration) []map[string]interface{} {
var encryptionConfiguration []map[string]interface{}
rules := make([]interface{}, 0, len(c.Rules))
for _, v := range c.Rules {
if v.ApplyServerSideEncryptionByDefault != nil {
r := make(map[string]interface{})
d := make(map[string]interface{})
d["kms_master_key_id"] = aws.StringValue(v.ApplyServerSideEncryptionByDefault.KMSMasterKeyID)
d["sse_algorithm"] = aws.StringValue(v.ApplyServerSideEncryptionByDefault.SSEAlgorithm)
r["apply_server_side_encryption_by_default"] = []map[string]interface{}{d}
rules = append(rules, r)
}
}
encryptionConfiguration = append(encryptionConfiguration, map[string]interface{}{
"rule": rules,
})
return encryptionConfiguration
}

func validateBucketPermissions(permissions []interface{}) error {
var (
fullControl bool
Expand Down
101 changes: 101 additions & 0 deletions yandex/resource_yandex_storage_bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/yandex-cloud/go-genproto/yandex/cloud/iam/v1/awscompatibility"
"github.com/yandex-cloud/go-genproto/yandex/cloud/kms/v1"
)

func init() {
Expand Down Expand Up @@ -452,6 +453,43 @@ func TestAccStorageBucket_UpdateGrant(t *testing.T) {
})
}

func TestAccStorageBucket_SSE(t *testing.T) {
rInt := acctest.RandInt()
resourceName := "yandex_storage_bucket.test"

keyName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
var symmetricKey kms.SymmetricKey

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
IDRefreshName: resourceName,
Providers: testAccProviders,
CheckDestroy: testAccCheckStorageBucketSSEDestroy,
Steps: []resource.TestStep{
{
Config: testAccStorageBucketSSEDefault(keyName, rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckKMSSymmetricKeyExists(
"yandex_kms_symmetric_key.key-a", &symmetricKey),
testAccCheckStorageBucketExists(resourceName),
testAccCheckStorageBucketSSE(resourceName,
&s3.ServerSideEncryptionConfiguration{
Rules: []*s3.ServerSideEncryptionRule{
{
ApplyServerSideEncryptionByDefault: &s3.ServerSideEncryptionByDefault{
KMSMasterKeyID: &symmetricKey.Id,
SSEAlgorithm: aws.String(s3.ServerSideEncryptionAwsKms),
},
},
},
},
),
),
},
},
})
}

func TestStorageBucketName(t *testing.T) {
validNames := []string{
"foobar",
Expand Down Expand Up @@ -486,6 +524,14 @@ func testAccCheckStorageBucketDestroy(s *terraform.State) error {
return testAccCheckStorageBucketDestroyWithProvider(s, testAccProvider)
}

func testAccCheckStorageBucketSSEDestroy(s *terraform.State) error {
err := testAccCheckStorageBucketDestroyWithProvider(s, testAccProvider)
if err != nil {
return err
}
return testAccCheckKMSSymmetricKeyDestroy(s)
}

func testAccCheckStorageBucketDestroyWithProvider(s *terraform.State, provider *schema.Provider) error {
config := provider.Meta().(*Config)

Expand Down Expand Up @@ -676,6 +722,30 @@ func testAccCheckStorageBucketCors(n string, corsRules []*s3.CORSRule) resource.
}
}

func testAccCheckStorageBucketSSE(n string, config *s3.ServerSideEncryptionConfiguration) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs := s.RootModule().Resources[n]
conn, err := getS3ClientByKeys(rs.Primary.Attributes["access_key"], rs.Primary.Attributes["secret_key"],
testAccProvider.Meta().(*Config))
if err != nil {
return err
}

out, err := conn.GetBucketEncryption(&s3.GetBucketEncryptionInput{
Bucket: aws.String(rs.Primary.ID),
})
if err != nil && !isAWSErr(err, "NoSuchEncryptionConfiguration", "") {
return fmt.Errorf("func GetBucketCors error: %v", err)
}

if !reflect.DeepEqual(out.ServerSideEncryptionConfiguration, config) {
return fmt.Errorf("bad error cors rule, expected: %v, got %v", config, out.ServerSideEncryptionConfiguration)
}

return nil
}
}

//// These need a bit of randomness as the name can only be used once globally
func testAccBucketName(randInt int) string {
return fmt.Sprintf("tf-test-bucket-%d", randInt)
Expand Down Expand Up @@ -883,6 +953,37 @@ resource "yandex_storage_bucket" "test" {
`, randInt, userID) + testAccCommonIamDependenciesAdminConfig(randInt)
}

func testAccStorageBucketSSEDefault(keyName string, randInt int) string {
return fmt.Sprintf(`
resource "yandex_kms_symmetric_key" "key-a" {
name = "%s"
description = "description for key-a"
default_algorithm = "AES_128"
rotation_period = "24h"
labels = {
tf-label = "tf-label-value-a"
empty-label = ""
}
}
resource "yandex_storage_bucket" "test" {
access_key = yandex_iam_service_account_static_access_key.sa-key.access_key
secret_key = yandex_iam_service_account_static_access_key.sa-key.secret_key
bucket = "tf-test-bucket-%d"
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
kms_master_key_id = yandex_kms_symmetric_key.key-a.id
sse_algorithm = "aws:kms"
}
}
}
}
`, keyName, randInt) + testAccCommonIamDependenciesAdminConfig(randInt)
}

func testAccStorageBucketBasic(randInt int) string {
return fmt.Sprintf(`
resource "yandex_storage_bucket" "test" {
Expand Down

0 comments on commit b46be90

Please sign in to comment.