Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BigQuery Dataset default CMEK encryption #1081

Merged
merged 1 commit into from
Oct 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions google-beta/resource_big_query_dataset.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,19 @@ func resourceBigQueryDataset() *schema.Resource {
Elem: bigqueryDatasetAccessSchema(),
// Default schema.HashSchema is used.
},
"default_encryption_configuration": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"kms_key_name": {
Type: schema.TypeString,
Required: true,
},
},
},
},
"default_partition_expiration_ms": {
Type: schema.TypeInt,
Optional: true,
Expand Down Expand Up @@ -241,6 +254,12 @@ func resourceBigQueryDatasetCreate(d *schema.ResourceData, meta interface{}) err
} else if v, ok := d.GetOkExists("location"); !isEmptyValue(reflect.ValueOf(locationProp)) && (ok || !reflect.DeepEqual(v, locationProp)) {
obj["location"] = locationProp
}
defaultEncryptionConfigurationProp, err := expandBigQueryDatasetDefaultEncryptionConfiguration(d.Get("default_encryption_configuration"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("default_encryption_configuration"); !isEmptyValue(reflect.ValueOf(defaultEncryptionConfigurationProp)) && (ok || !reflect.DeepEqual(v, defaultEncryptionConfigurationProp)) {
obj["defaultEncryptionConfiguration"] = defaultEncryptionConfigurationProp
}

url, err := replaceVars(d, config, "{{BigQueryBasePath}}projects/{{project}}/datasets")
if err != nil {
Expand Down Expand Up @@ -335,6 +354,9 @@ func resourceBigQueryDatasetRead(d *schema.ResourceData, meta interface{}) error
if err := d.Set("location", flattenBigQueryDatasetLocation(res["location"], d)); err != nil {
return fmt.Errorf("Error reading Dataset: %s", err)
}
if err := d.Set("default_encryption_configuration", flattenBigQueryDatasetDefaultEncryptionConfiguration(res["defaultEncryptionConfiguration"], d)); err != nil {
return fmt.Errorf("Error reading Dataset: %s", err)
}
if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil {
return fmt.Errorf("Error reading Dataset: %s", err)
}
Expand Down Expand Up @@ -399,6 +421,12 @@ func resourceBigQueryDatasetUpdate(d *schema.ResourceData, meta interface{}) err
} else if v, ok := d.GetOkExists("location"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, locationProp)) {
obj["location"] = locationProp
}
defaultEncryptionConfigurationProp, err := expandBigQueryDatasetDefaultEncryptionConfiguration(d.Get("default_encryption_configuration"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("default_encryption_configuration"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, defaultEncryptionConfigurationProp)) {
obj["defaultEncryptionConfiguration"] = defaultEncryptionConfigurationProp
}

url, err := replaceVars(d, config, "{{BigQueryBasePath}}projects/{{project}}/datasets/{{dataset_id}}")
if err != nil {
Expand Down Expand Up @@ -618,6 +646,23 @@ func flattenBigQueryDatasetLocation(v interface{}, d *schema.ResourceData) inter
return v
}

func flattenBigQueryDatasetDefaultEncryptionConfiguration(v interface{}, d *schema.ResourceData) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["kms_key_name"] =
flattenBigQueryDatasetDefaultEncryptionConfigurationKmsKeyName(original["kmsKeyName"], d)
return []interface{}{transformed}
}
func flattenBigQueryDatasetDefaultEncryptionConfigurationKmsKeyName(v interface{}, d *schema.ResourceData) interface{} {
return v
}

func expandBigQueryDatasetAccess(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
v = v.(*schema.Set).List()
l := v.([]interface{})
Expand Down Expand Up @@ -787,3 +832,26 @@ func expandBigQueryDatasetLabels(v interface{}, d TerraformResourceData, config
func expandBigQueryDatasetLocation(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandBigQueryDatasetDefaultEncryptionConfiguration(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedKmsKeyName, err := expandBigQueryDatasetDefaultEncryptionConfigurationKmsKeyName(original["kms_key_name"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedKmsKeyName); val.IsValid() && !isEmptyValue(val) {
transformed["kmsKeyName"] = transformedKmsKeyName
}

return transformed, nil
}

func expandBigQueryDatasetDefaultEncryptionConfigurationKmsKeyName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}
51 changes: 51 additions & 0 deletions google-beta/resource_big_query_dataset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,29 @@ func TestAccBigQueryDataset_regionalLocation(t *testing.T) {
})
}

func TestAccBigQueryDataset_cmek(t *testing.T) {
t.Parallel()

kms := BootstrapKMSKeyInLocation(t, "us")
pid := getTestProjectFromEnv()
datasetID1 := fmt.Sprintf("tf_test_%s", acctest.RandString(10))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccBigQueryDataset_cmek(pid, datasetID1, kms.CryptoKey.Name),
},
{
ResourceName: "google_bigquery_dataset.test",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccAddTable(datasetID string, tableID string) resource.TestCheckFunc {
// Not actually a check, but adds a table independently of terraform
return func(s *terraform.State) error {
Expand Down Expand Up @@ -303,3 +326,31 @@ resource "google_bigquery_dataset" "access_test" {
}
}`, otherDatasetID, otherTableID, datasetID)
}

func testAccBigQueryDataset_cmek(pid, datasetID, kmsKey string) string {
return fmt.Sprintf(`
data "google_project" "project" {
project_id = "%s"
}

resource "google_project_iam_member" "kms-project-binding" {
project = "${data.google_project.project.project_id}"
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
member = "serviceAccount:bq-${data.google_project.project.number}@bigquery-encryption.iam.gserviceaccount.com"
}

resource "google_bigquery_dataset" "test" {
dataset_id = "%s"
friendly_name = "test"
description = "This is a test description"
location = "US"
default_table_expiration_ms = 3600000

default_encryption_configuration {
kms_key_name = "%s"
}

project = "${google_project_iam_member.kms-project-binding.project}"
}
`, pid, datasetID, kmsKey)
}
40 changes: 40 additions & 0 deletions website/docs/r/bigquery_dataset.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,32 @@ resource "google_bigquery_dataset" "dataset" {
}
}
```
## Example Usage - Bigquery Dataset Cmek


```hcl
resource "google_bigquery_dataset" "dataset" {
dataset_id = "example_dataset"
friendly_name = "test"
description = "This is a test description"
location = "US"
default_table_expiration_ms = 3600000

default_encryption_configuration {
kms_key_name = "${google_kms_crypto_key.crypto_key.self_link}"
}
}

resource "google_kms_crypto_key" "crypto_key" {
name = "example-key"
key_ring = "${google_kms_key_ring.key_ring.self_link}"
}

resource "google_kms_key_ring" "key_ring" {
name = "example-keyring"
location = "us"
}
```

## Argument Reference

Expand Down Expand Up @@ -139,6 +165,12 @@ The following arguments are supported:
The default value is multi-regional location `US`.
Changing this forces a new resource to be created.

* `default_encryption_configuration` -
(Optional)
The default encryption key for all tables in the dataset. Once this property is set,
all newly-created partitioned tables in the dataset will have encryption key set to
this value, unless table creation request (or query) overrides the key. Structure is documented below.

* `project` - (Optional) The ID of the project in which the resource belongs.
If it is not provided, the provider project is used.

Expand Down Expand Up @@ -210,6 +242,14 @@ The `view` block supports:
A-Z), numbers (0-9), or underscores (_). The maximum length
is 1,024 characters.

The `default_encryption_configuration` block supports:

* `kms_key_name` -
(Required)
Describes the Cloud KMS encryption key that will be used to protect destination
BigQuery table. The BigQuery Service Account associated with your project requires
access to this encryption key.

## Attributes Reference

In addition to the arguments listed above, the following computed attributes are exported:
Expand Down