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

Add EncryptionConfig to Cloud Composer's EnvironmentConfig #4310

Merged
merged 5 commits into from
Feb 17, 2021
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ var (
<% unless version == "ga" -%>
"config.0.database_config",
"config.0.web_server_config",
"config.0.encryption_config",
<% end -%>
}

Expand Down Expand Up @@ -433,6 +434,23 @@ func resourceComposerEnvironment() *schema.Resource {
},
},
},
"encryption_config": {
Type: schema.TypeList,
Optional: true,
Computed: true,
AtLeastOneOf: composerConfigKeys,
MaxItems: 1,
Description: `The encryption options for the Composer environment and its dependencies.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"kms_key_name": {
Type: schema.TypeString,
Required: true,
Description: `Optional. Customer-managed Encryption Key available through Google's Key Management Service. Cannot be updated.`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this cannot be updated as indicated by the description, it should probably be marked ForceNew: true to force Terraform to recreate the resource if this field is changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, added!

With regard to tests - I've noticed some problems with deletion after the test is complete (a firewall rule related issue, which, based on the comments, is known to happen), but nothing at creation.

},
},
},
},
<% end -%>
"airflow_uri": {
Type: schema.TypeString,
Expand Down Expand Up @@ -826,6 +844,7 @@ func flattenComposerEnvironmentConfig(envCfg *composer.EnvironmentConfig) interf
<% unless version == "ga" -%>
transformed["database_config"] = flattenComposerEnvironmentConfigDatabaseConfig(envCfg.DatabaseConfig)
transformed["web_server_config"] = flattenComposerEnvironmentConfigWebServerConfig(envCfg.WebServerConfig)
transformed["encryption_config"] = flattenComposerEnvironmentConfigEncryptionConfig(envCfg.EncryptionConfig)
<% end -%>

return []interface{}{transformed}
Expand Down Expand Up @@ -876,6 +895,17 @@ func flattenComposerEnvironmentConfigWebServerConfig(webServerCfg *composer.WebS

return []interface{}{transformed}
}

func flattenComposerEnvironmentConfigEncryptionConfig(encryptionCfg *composer.EncryptionConfig) interface{} {
if encryptionCfg == nil {
return nil
}

transformed := make(map[string]interface{})
transformed["kms_key_name"] = encryptionCfg.KmsKeyName

return []interface{}{transformed}
}
<% end -%>

func flattenComposerEnvironmentConfigPrivateEnvironmentConfig(envCfg *composer.PrivateEnvironmentConfig) interface{} {
Expand Down Expand Up @@ -1006,6 +1036,12 @@ func expandComposerEnvironmentConfig(v interface{}, d *schema.ResourceData, conf
}
transformed.WebServerConfig = transformedWebServerConfig

transformedEncryptionConfig, err := expandComposerEnvironmentConfigEncryptionConfig(original["encryption_config"], d, config)
if err != nil {
return nil, err
}
transformed.EncryptionConfig = transformedEncryptionConfig

<% end -%>
return transformed, nil
}
Expand Down Expand Up @@ -1080,6 +1116,23 @@ func expandComposerEnvironmentConfigWebServerConfig(v interface{}, d *schema.Res

<% end -%>

<% unless version == "ga" -%>
func expandComposerEnvironmentConfigEncryptionConfig(v interface{}, d *schema.ResourceData, config *Config) (*composer.EncryptionConfig, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})

transformed := &composer.EncryptionConfig{}
transformed.KmsKeyName = original["kms_key_name"].(string)

return transformed, nil
}

<% end -%>

func expandComposerEnvironmentConfigPrivateEnvironmentConfig(v interface{}, d *schema.ResourceData, config *Config) (*composer.PrivateEnvironmentConfig, error) {
l := v.([]interface{})
if len(l) == 0 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,41 @@ func TestAccComposerEnvironment_withWebServerConfig(t *testing.T) {
},
})
}

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

kms := BootstrapKMSKeyInLocation(t, "us-central1")
pid := getTestProjectFromEnv()
envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, randInt(t))
network := fmt.Sprintf("%s-%d", testComposerNetworkPrefix, randInt(t))
subnetwork := network + "-1"

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccComposerEnvironmentDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComposerEnvironment_encryptionCfg(pid, envName, kms.CryptoKey.Name, network, subnetwork),
},
{
ResourceName: "google_composer_environment.test",
ImportState: true,
ImportStateVerify: true,
},
// This is a terrible clean-up step in order to get destroy to succeed,
// due to dangling firewall rules left by the Composer Environment blocking network deletion.
// TODO(dzarmola): Remove this check if firewall rules bug gets fixed by Composer.
{
PlanOnly: true,
ExpectNonEmptyPlan: false,
Config: testAccComposerEnvironment_encryptionCfg(pid, envName, kms.CryptoKey.Name, network, subnetwork),
Check: testAccCheckClearComposerEnvironmentFirewalls(t, network),
},
},
})
}
<% end -%>
// Checks behavior of node config, including dependencies on Compute resources.
func TestAccComposerEnvironment_withNodeConfig(t *testing.T) {
Expand Down Expand Up @@ -735,6 +770,72 @@ resource "google_compute_subnetwork" "test" {
`, name, network, subnetwork)
}

func testAccComposerEnvironment_encryptionCfg(pid, name, kmsKey, network, subnetwork string) string {
return fmt.Sprintf(`
data "google_project" "project" {
project_id = "%s"
}
resource "google_project_iam_member" "kms-project-binding1" {
project = data.google_project.project.project_id
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
member = "serviceAccount:service-${data.google_project.project.number}@cloudcomposer-accounts.iam.gserviceaccount.com"
}
resource "google_project_iam_member" "kms-project-binding2" {
project = data.google_project.project.project_id
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
member = "serviceAccount:service-${data.google_project.project.number}@compute-system.iam.gserviceaccount.com"
}
resource "google_project_iam_member" "kms-project-binding3" {
project = data.google_project.project.project_id
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
member = "serviceAccount:service-${data.google_project.project.number}@container-engine-robot.iam.gserviceaccount.com"
}
resource "google_project_iam_member" "kms-project-binding4" {
project = data.google_project.project.project_id
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com"
}
resource "google_project_iam_member" "kms-project-binding5" {
project = data.google_project.project.project_id
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-pubsub.iam.gserviceaccount.com"
}
resource "google_kms_crypto_key_iam_member" "iam" {
crypto_key_id = "%s"
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
member = "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com"
}
resource "google_composer_environment" "test" {
depends_on = [google_project_iam_member.kms-project-binding1, google_project_iam_member.kms-project-binding2,
google_project_iam_member.kms-project-binding3, google_project_iam_member.kms-project-binding4,
google_project_iam_member.kms-project-binding5, google_kms_crypto_key_iam_member.iam]
name = "%s"
region = "us-central1"
config {
node_config {
network = google_compute_network.test.self_link
subnetwork = google_compute_subnetwork.test.self_link
zone = "us-central1-a"
}
encryption_config {
kms_key_name = "%s"
}
}
}
// use a separate network to avoid conflicts with other tests running in parallel
// that use the default network/subnet
resource "google_compute_network" "test" {
name = "%s"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "test" {
name = "%s"
ip_cidr_range = "10.2.0.0/16"
region = "us-central1"
network = google_compute_network.test.self_link
}
`, pid, kmsKey, name, kmsKey, network, subnetwork)
}
<% end -%>
func testAccComposerEnvironment_update(name, network, subnetwork string) string {
return fmt.Sprintf(`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ The `config` block supports:
(Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html))
The configuration settings for the Airflow web server App Engine instance.

* `encryption_config` -
(Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html))
The encryption options for the Cloud Composer environment and its dependencies.

The `node_config` block supports:

* `zone` -
Expand Down Expand Up @@ -390,6 +394,13 @@ The `web_server_config` block supports:
Value custom is returned only in response, if Airflow web server parameters were
manually changed to a non-standard values.

The `encryption_config` block supports:

* `kms_key_name` -
(Required)
Customer-managed Encryption Key available through Google's Key Management Service. It must
be the fully qualified resource name,
i.e. projects/project-id/locations/location/keyRings/keyring/cryptoKeys/key. Cannot be updated.


## Attributes Reference
Expand Down