diff --git a/README.md b/README.md
index 5a0295bb1..55179fbe6 100644
--- a/README.md
+++ b/README.md
@@ -72,6 +72,14 @@ The following resources are available in the InSpec GCP Profile
- [google_container_clusters](docs/resources/google_container_clusters.md)
- [google_container_node_pool](docs/resources/google_container_node_pool.md)
- [google_container_node_pools](docs/resources/google_container_node_pools.md)
+- [google_kms_crypto_key](docs/resources/google_kms_crypto_key.md)
+- [google_kms_crypto_key_iam_binding](docs/resources/google_kms_crypto_key_iam_binding.md)
+- [google_kms_crypto_key_iam_bindings](docs/resources/google_kms_crypto_key_iam_bindings.md)
+- [google_kms_crypto_keys](docs/resources/google_kms_crypto_keys.md)
+- [google_kms_key_ring](docs/resources/google_kms_key_ring.md)
+- [google_kms_key_ring_iam_binding](docs/resources/google_kms_key_ring_iam_binding.md)
+- [google_kms_key_ring_iam_bindings](docs/resources/google_kms_key_ring_iam_bindings.md)
+- [google_kms_key_rings](docs/resources/google_kms_key_rings.md)
- [google_project](docs/resources/google_project.md)
- [google_project_iam_binding](docs/resources/google_project_iam_binding.md)
- [google_project_iam_bindings](docs/resources/google_project_iam_bindings.md)
diff --git a/docs/resources/google_kms_crypto_key.md b/docs/resources/google_kms_crypto_key.md
new file mode 100644
index 000000000..7ecdd25e9
--- /dev/null
+++ b/docs/resources/google_kms_crypto_key.md
@@ -0,0 +1,62 @@
+---
+title: About the google_kms_crypto_key Resource
+platform: gcp
+---
+
+# google\_kms\_crypto\_key
+
+Use the `google_kms_crypto_key` InSpec audit resource to test properties of a single GCP KMS crypto key. See [this page](https://cloud.google.com/kms/docs/object-hierarchy?hl=en_US&_ga=2.223343707.-1730338523.1522320263#cryptokeyversion) for useful background.
+
+
+
+## Syntax
+
+A `google_kms_crypto_key` resource block declares the tests for a single GCP KMS crypto key by project, location, key ring name and key name.
+
+ describe google_kms_crypto_key(project: 'chef-inspec-gcp', location: 'us-east1', key_ring_name: 'key-ring', name: 'crypto-key') do
+ it { should exist }
+ end
+
+
+
+## Examples
+
+The following examples show how to use this InSpec audit resource.
+
+### Test that a GCP KMS crypto key was created recently
+
+ describe google_kms_crypto_key(project: 'chef-inspec-gcp', location: 'us-east1', key_ring_name: 'key-ring', name: 'crypto-key') do
+ its('create_time_date') { should be > Time.now - 365*60*60*24*10 }
+ end
+
+### Test when the next rotation time for a GCP KMS crypto key is scheduled
+
+ describe google_kms_crypto_key(project: 'chef-inspec-gcp', location: 'us-east1', key_ring_name: 'key-ring', name: 'crypto-key') do
+ its('next_rotation_time_date') { should be > Time.now - 100000 }
+ end
+
+### Check that the crypto key purpose is as expected
+
+ describe google_kms_crypto_key(project: 'chef-inspec-gcp', location: 'us-east1', key_ring_name: 'key-ring', name: 'crypto-key') do
+ its('purpose') { should eq "ENCRYPT_DECRYPT" }
+ end
+
+### Check that the crypto key primary is in "ENABLED" state
+
+ describe google_kms_crypto_key(project: 'chef-inspec-gcp', location: 'us-east1', key_ring_name: 'key-ring', name: 'crypto-key') do
+ its('primary_state') { should eq "ENABLED" }
+ end
+
+
+
+
+## Properties
+
+* `create_time`, `create_time_date`, `name`, `crypto_key_name`, `crypto_key_url`, `next_rotation_time`, `next_rotation_time_date`, `primary_create_time`, `primary_create_time_date`, `primary_name`, `primary_state`, `purpose`, `rotation_period`
+
+
+
+
+## GCP Permissions
+
+Ensure the [Cloud Key Management Service (KMS) API](https://console.cloud.google.com/apis/library/cloudkms.googleapis.com/) is enabled for the project where the resource is located.
\ No newline at end of file
diff --git a/docs/resources/google_kms_crypto_key_iam_binding.md b/docs/resources/google_kms_crypto_key_iam_binding.md
new file mode 100644
index 000000000..1e8e243b5
--- /dev/null
+++ b/docs/resources/google_kms_crypto_key_iam_binding.md
@@ -0,0 +1,49 @@
+---
+title: About the google_kms_crypto_key_iam_binding Resource
+platform: gcp
+---
+
+# google\_kms\_crypto\_key\_iam\_binding
+
+Use the `google_kms_crypto_key_iam_binding` InSpec audit resource to test properties of a single GCP KMS Crypto Key IAM Binding.
+
+
+
+## Syntax
+
+A `google_kms_crypto_key_iam_binding` resource block declares the tests for a single KMS Crypto Key IAM Binding for specified role.
+
+ describe google_kms_crypto_key_iam_binding(crypto_key_url: 'projects/project/locations/europe-west2/keyRings/key-ring/cryptoKeys/key-name', role: "roles/owner") do
+ it { should exist }
+ end
+
+
+
+## Examples
+
+The following examples show how to use this InSpec audit resource.
+
+### Test that a GCP KMS Crypto Key IAM Binding exists for the specified role
+
+ describe google_kms_crypto_key_iam_binding(crypto_key_url: 'projects/project/locations/europe-west2/keyRings/key-ring/cryptoKeys/key-name', role: "roles/owner") do
+ it { should exist }
+ end
+
+### Test that a GCP KMS Crypto Key IAM Binding has the desired user included for the specified role
+
+ describe google_kms_crypto_key_iam_binding(crypto_key_url: 'projects/project/locations/europe-west2/keyRings/key-ring/cryptoKeys/key-name', role: "roles/owner") do
+ its('members') {should include 'user:someuser@domain.com' }
+ end
+
+
+
+## Properties
+
+* `members`
+
+
+
+
+## GCP Permissions
+
+Ensure the [Cloud Key Management Service (KMS) API](https://console.cloud.google.com/apis/library/cloudkms.googleapis.com/) is enabled for the project where the resource is located.
\ No newline at end of file
diff --git a/docs/resources/google_kms_crypto_key_iam_bindings.md b/docs/resources/google_kms_crypto_key_iam_bindings.md
new file mode 100644
index 000000000..b8dcdc5bd
--- /dev/null
+++ b/docs/resources/google_kms_crypto_key_iam_bindings.md
@@ -0,0 +1,68 @@
+---
+title: About the google_kms_crypto_key_iam_bindings Resource
+platform: gcp
+---
+
+# google\_kms\_crypto\_key\_iam\_bindings
+
+Use the `google_kms_crypto_key_iam_bindings` InSpec audit resource to test properties of all, or a filtered group of, GCP KMS Crypto Key IAM Bindings.
+
+
+
+## Syntax
+
+A `google_kms_crypto_key_iam_bindings` resource block collects GCP KMS Crypto Key IAM Bindings then tests that group.
+
+ describe google_kms_crypto_key_iam_bindings(crypto_key_url: 'projects/project/locations/europe-west2/keyRings/key-ring/cryptoKeys/key-name') do
+ it { should exist }
+ end
+
+Use this InSpec resource to enumerate roles then test in-depth using `google_kms_key_ring_iam_binding`.
+
+ google_kms_crypto_key_iam_bindings(crypto_key_url: 'projects/project/locations/europe-west2/keyRings/key-ring/cryptoKeys/key-name').iam_binding_roles.each do |iam_binding_role|
+ describe google_kms_crypto_key_iam_binding(crypto_key_url: 'projects/project/locations/europe-west2/keyRings/key-ring/cryptoKeys/key-name', role: "roles/owner") do
+ it { should exist }
+ its('members') {should include 'user:someuser@domain.com' }
+ end
+ end
+
+
+
+## Examples
+
+The following examples show how to use this InSpec audit resource.
+
+### Test that there are no more than a specified number of IAM bindings roles available for the crypto key
+
+ describe google_kms_crypto_key_iam_bindings(crypto_key_url: 'projects/project/locations/europe-west2/keyRings/key-ring/cryptoKeys/key-name') do
+ its('count') { should be <= 100}
+ end
+
+### Test that an expected IAM binding is available for the crypto key
+
+ describe google_kms_crypto_key_iam_bindings(crypto_key_url: 'projects/project/locations/europe-west2/keyRings/key-ring/cryptoKeys/key-name') do
+ its('iam_binding_roles') { should include "roles/storage.admin" }
+ end
+
+### Test that a particular role does not exist using filtering of the plural resource
+
+ describe google_kms_crypto_key_iam_bindings(crypto_key_url: 'projects/project/locations/europe-west2/keyRings/key-ring/cryptoKeys/key-name').where(iam_binding_role: "roles/iam.securityReviewer") do
+ it { should_not exist }
+ end
+
+
+
+## Filter Criteria
+
+This resource supports the following filter criteria: `iam_binding_role`. This may be used with `where`, as a block or as a method.
+
+## Properties
+
+* `iam_binding_roles` - an array of google_kms_crypto_key_iam_binding role strings e.g. `["roles/compute.admin", "roles/owner"]`
+
+
+
+
+## GCP Permissions
+
+Ensure the [Cloud Key Management Service (KMS) API](https://console.cloud.google.com/apis/library/cloudkms.googleapis.com/) is enabled for the project where the resource is located.s
\ No newline at end of file
diff --git a/docs/resources/google_kms_crypto_keys.md b/docs/resources/google_kms_crypto_keys.md
new file mode 100644
index 000000000..59005057d
--- /dev/null
+++ b/docs/resources/google_kms_crypto_keys.md
@@ -0,0 +1,65 @@
+---
+title: About the google_kms_crypto_keys Resource
+platform: gcp
+---
+
+# google\_kms\_crypto\_keys
+
+Use the `google_kms_crypto_keys` InSpec audit resource to test properties of all, or a filtered group of, GCP KMS crypto keys for supplied project, location and key ring name.
+
+
+
+## Syntax
+
+A `google_kms_crypto_keys` resource block collects GCP KMS crypto keys then tests that group.
+
+ describe google_kms_crypto_keys(project: 'chef-inspec-gcp', location: 'us-east1', key_ring_name: 'key-ring') do
+ it { should exist }
+ end
+
+Use this InSpec resource to enumerate IDs then test in-depth using `google_kms_crypto_key`.
+
+ describe google_kms_crypto_keys(project: 'chef-inspec-gcp', location: 'us-east1', key_ring_name: 'key-ring').crypto_key_names.each do |key_name|
+ describe google_kms_crypto_key(project: 'chef-inspec-gcp', location: 'us-east1', key_ring_name: 'key-ring', name: key_name) do
+ it { should exist }
+ its('create_time_date') { should be > Time.now - 365*60*60*24*10 }
+ its('purpose') { should eq "ENCRYPT_DECRYPT" }
+ its('primary_state') { should eq "ENABLED" }
+ end
+ end
+
+
+
+## Examples
+
+The following examples show how to use this InSpec audit resource.
+
+### Test that there are no more than a specified number of keys in the key ring
+
+ describe google_kms_crypto_keys(project: 'chef-inspec-gcp', location: 'us-east1', key_ring_name: 'key-ring') do
+ its('count') { should be <= 100}
+ end
+
+### Test that an expected key name is present in the key ring
+
+ describe google_kms_crypto_keys(project: 'chef-inspec-gcp', location: 'us-east1', key_ring_name: 'key-ring') do
+ its('crypto_key_names') { should include "my-crypto-key-name" }
+ end
+
+
+
+## Filter Criteria
+
+This resource supports the following filter criteria: `key_name`. This may be used with `where`, as a block or as a method.
+
+## Properties
+
+* `crypto_key_names` - an array of google_kms_crypto_key name strings e.g. `['key-name']`
+* `crypto_key_urls` - an array of google_kms_crypto_key url strings e.g. `['projects/PROJECT/locations/LOCATION/keyRings/key-ring-name/cryptoKeys/key-name']`
+
+
+
+
+## GCP Permissions
+
+Ensure the [Cloud Key Management Service (KMS) API](https://console.cloud.google.com/apis/library/cloudkms.googleapis.com/) is enabled for the project where the resource is located.
\ No newline at end of file
diff --git a/docs/resources/google_kms_key_ring.md b/docs/resources/google_kms_key_ring.md
new file mode 100644
index 000000000..546d35006
--- /dev/null
+++ b/docs/resources/google_kms_key_ring.md
@@ -0,0 +1,51 @@
+---
+title: About the google_kms_key_ring Resource
+platform: gcp
+---
+
+# google\_kms\_key\_ring
+
+Use the `google_kms_key_ring` InSpec audit resource to test properties of a single GCP kms key ring.
+
+
+
+## Syntax
+
+A `google_kms_key_ring` resource block declares the tests for a single GCP key ring by project and name.
+
+ describe google_kms_key_ring(project: 'chef-inspec-gcp', location: 'us-east1', name: 'key-ring-name') do
+ it { should exist }
+ end
+
+
+
+## Examples
+
+The following examples show how to use this InSpec audit resource.
+
+### Test that a GCP kms key ring exists
+
+ describe google_kms_key_ring(project: 'chef-inspec-gcp', location: 'us-east1', name: 'key-ring-name') do
+ it { should exist }
+ end
+
+### Test that a GCP kms key ring is in the expected state
+
+For any existing key ring, below should definitely be true!
+
+ describe google_kms_key_ring(project: 'chef-inspec-gcp', location: 'us-east1', name: 'key-ring-name') do
+ its('create_time_date') { should be > Time.now - 365*60*60*24*50 }
+ end
+
+
+
+## Properties
+
+* `create_time`, `create_time_date`, `name`, `key_ring_name`, `key_ring_url`
+
+
+
+
+## GCP Permissions
+
+Ensure the [Cloud Key Management Service (KMS) API](https://console.cloud.google.com/apis/library/cloudkms.googleapis.com/) is enabled for the project where the resource is located.
\ No newline at end of file
diff --git a/docs/resources/google_kms_key_ring_iam_binding.md b/docs/resources/google_kms_key_ring_iam_binding.md
new file mode 100644
index 000000000..19a68b00f
--- /dev/null
+++ b/docs/resources/google_kms_key_ring_iam_binding.md
@@ -0,0 +1,50 @@
+---
+title: About the google_kms_key_ring_iam_binding Resource
+platform: gcp
+---
+
+# google\_kms\_key\_ring\_iam\_binding
+
+Use the `google_kms_key_ring_iam_binding` InSpec audit resource to test properties of a single GCP KMS key ring IAM binding.
+
+
+
+## Syntax
+
+A `google_kms_key_ring_iam_binding` resource block declares the tests for a single GCP KMS key ring IAM binding by role.
+
+ describe google_kms_key_ring_iam_binding(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring', role: 'roles/compute.admin') do
+ it { should exist }
+ its('members') {should include 'user:someuser@domain.com' }
+ end
+
+
+
+## Examples
+
+The following examples show how to use this InSpec audit resource.
+
+### Test that a GCP project KMS key ring IAM binding exists
+
+ describe google_kms_key_ring_iam_binding(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring', role: 'roles/compute.admin') do
+ it { should exist }
+ end
+
+### Test that a GCP project KMS key ring IAM binding has the desired user included
+
+ describe google_kms_key_ring_iam_binding(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring', role: 'roles/compute.admin') do
+ its('members') {should include 'user:someuser@domain.com' }
+ end
+
+
+
+## Properties
+
+* `members`
+
+
+
+
+## GCP Permissions
+
+Ensure the [Cloud Key Management Service (KMS) API](https://console.cloud.google.com/apis/library/cloudkms.googleapis.com/) is enabled for the project where the resource is located.
\ No newline at end of file
diff --git a/docs/resources/google_kms_key_ring_iam_bindings.md b/docs/resources/google_kms_key_ring_iam_bindings.md
new file mode 100644
index 000000000..aae8df8df
--- /dev/null
+++ b/docs/resources/google_kms_key_ring_iam_bindings.md
@@ -0,0 +1,68 @@
+---
+title: About the google_kms_key_ring_iam_bindings Resource
+platform: gcp
+---
+
+# google\_kms\_key\_ring\_iam\_bindings
+
+Use the `google_kms_key_ring_iam_bindings` InSpec audit resource to test properties of all, or a filtered group of, GCP KMS key ring IAM bindings.
+
+
+
+## Syntax
+
+A `google_kms_key_ring_iam_bindings` resource block collects GCP KMS key ring IAM bindings then tests that group.
+
+ describe google_kms_key_ring_iam_bindings(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring') do
+ it { should exist }
+ end
+
+Use this InSpec resource to enumerate roles then test in-depth using `google_kms_key_ring_iam_binding`.
+
+ google_kms_key_ring_iam_bindings(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring').iam_binding_roles.each do |iam_binding_role|
+ describe google_kms_key_ring_iam_binding(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring', role: "roles/owner") do
+ it { should exist }
+ its('members') {should include 'user:someuser@domain.com' }
+ end
+ end
+
+
+
+## Examples
+
+The following examples show how to use this InSpec audit resource.
+
+### Test that there are no more than a specified number of IAM bindings roles available for the key ring
+
+ describe google_kms_key_ring_iam_bindings(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring') do
+ its('count') { should be <= 100}
+ end
+
+### Test that an expected IAM binding is available for the key ring
+
+ describe google_kms_key_ring_iam_bindings(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring') do
+ its('iam_binding_roles') { should include "roles/storage.admin" }
+ end
+
+### Test that a particular role does not exist using filtering of the plural resource
+
+ describe google_kms_key_ring_iam_bindings(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring').where(iam_binding_role: "roles/iam.securityReviewer") do
+ it { should_not exist }
+ end
+
+
+
+## Filter Criteria
+
+This resource supports the following filter criteria: `iam_binding_role`. This may be used with `where`, as a block or as a method.
+
+## Properties
+
+* `iam_binding_roles` - an array of google_kms_key_ring_iam_binding role strings e.g. `["roles/compute.admin", "roles/owner"]`
+
+
+
+
+## GCP Permissions
+
+Ensure the [Cloud Key Management Service (KMS) API](https://console.cloud.google.com/apis/library/cloudkms.googleapis.com/) is enabled for the project where the resource is located.s
\ No newline at end of file
diff --git a/docs/resources/google_kms_key_rings.md b/docs/resources/google_kms_key_rings.md
new file mode 100644
index 000000000..3b59591fb
--- /dev/null
+++ b/docs/resources/google_kms_key_rings.md
@@ -0,0 +1,74 @@
+---
+title: About the google_kms_key_rings Resource
+platform: gcp
+---
+
+# google\_kms\_key\_rings
+
+Use the `google_kms_key_rings` InSpec audit resource to test properties of all, or a filtered group of, GCP KMS key rings for a project in a particular location.
+
+
+
+## Syntax
+
+A `google_kms_key_rings` resource block collects GCP kms_key_rings by project then tests that group.
+
+ describe google_kms_key_rings(project: 'chef-inspec-gcp', location: 'us-east1') do
+ it { should exist }
+ end
+
+Use this InSpec resource to enumerate IDs then test in-depth using `google_kms_key_ring`.
+
+ google_kms_key_rings(project: 'chef-inspec-gcp', location: 'us-east1').kms_key_ring_names.each do |kms_key_ring_name|
+ describe google_kms_key_ring(project: 'chef-inspec-gcp', kms_key_ring: kms_key_ring_name) do
+ it { should exist }
+ its('kind') { should eq "compute#kms_key_ring" }
+ its('status') { should eq 'UP' }
+ end
+ end
+
+
+
+## Examples
+
+The following examples show how to use this InSpec audit resource.
+
+### Test that there are no more than a specified number of kms_key_rings available for the project
+
+ describe google_kms_key_rings(project: 'chef-inspec-gcp', location: 'us-east1') do
+ its('count') { should be <= 200}
+ end
+
+### Test that an expected kms_key_ring is available for the project
+
+ describe google_kms_key_rings(project: 'chef-inspec-gcp', location: 'us-east1') do
+ its('key_ring_names') { should include "a-named-key" }
+ end
+
+
+### Test that all KMS key rings were created in the past year
+
+ describe google_kms_key_rings(project: gcp_project_id, location: 'us-east1').key_ring_names.each do |key_ring_name|
+ describe google_kms_key_ring(project: 'chef-inspec-gcp', location: 'us-east1', 'name: key_ring_name) do
+ it { should exist }
+ its('create_time_date') { should be > Time.now - 365*60*60*24 }
+ end
+ end
+
+
+
+## Filter Criteria
+
+This resource supports the following filter criteria: `key_ring_name`. This may be used with `where`, as a block or as a method.
+
+## Properties
+
+* `key_ring_names` - an array of google_kms_key_ring name strings e.g.`['key-ring-name']`
+* `key_ring_urls` - an array of google_kms_key_ring name url strings e.g. `['projects/PROJECT/locations/LOCATION/keyRings/key-ring-name']`
+
+
+
+
+## GCP Permissions
+
+Ensure the [Cloud Key Management Service (KMS) API](https://console.cloud.google.com/apis/library/cloudkms.googleapis.com/) is enabled for the project where the resource is located.
\ No newline at end of file
diff --git a/docs/resources/google_project_iam_binding.md b/docs/resources/google_project_iam_binding.md
index e53aee2e5..d7de9aa35 100644
--- a/docs/resources/google_project_iam_binding.md
+++ b/docs/resources/google_project_iam_binding.md
@@ -15,7 +15,6 @@ A `google_project_iam_binding` resource block declares the tests for a single GC
describe google_project_iam_binding(project: 'chef-inspec-gcp', role: 'roles/compute.admin') do
it { should exist }
- its('members') {should include 'user:someuser@domain.com' }
end
@@ -26,33 +25,25 @@ The following examples show how to use this InSpec audit resource.
### Test that a GCP project iam_binding exists
- describe google_project_iam_binding(project: 'chef-inspec-gcp', iam_binding: 'us-east1-b') do
+ describe google_project_iam_binding(project: 'chef-inspec-gcp', role: 'roles/compute.admin') do
it { should exist }
end
-### Test that a GCP project iam_binding is in the expected state
-
- describe google_project_iam_binding(project: 'chef-inspec-gcp', iam_binding: 'us-east1-b') do
- its('status') { should eq 'UP' }
- # or equivalently
- it { should be_up }
- end
+### Test that a GCP project IAM binding role has the desired user included
-### Test that a GCP project iam_binding has an expected CPU platform
-
- describe google_project_iam_binding(project: 'chef-inspec-gcp', iam_binding: 'us-east1-b') do
- its('available_cpu_platforms') { should include "Intel Skylake" }
+ describe google_project_iam_binding(project: 'chef-inspec-gcp', role: 'roles/compute.admin') do
+ its('members') {should include 'user:someuser@domain.com' }
end
## Properties
-* `available_cpu_platforms`, `creation_timestamp`, `description`, `id`, `kind`, `name`, `region`, `status`, `region_name`
+* `members`
## GCP Permissions
-Ensure the [Compute Engine API](https://console.cloud.google.com/apis/library/project.googleapis.com/) is enabled for the project where the resource is located.
\ No newline at end of file
+Ensure the [Cloud Resource Manager API](https://console.cloud.google.com/apis/library/cloudresourcemanager.googleapis.com/) is enabled for the project.
\ No newline at end of file
diff --git a/docs/resources/google_project_iam_bindings.md b/docs/resources/google_project_iam_bindings.md
index 23becbc38..05bfad6cc 100644
--- a/docs/resources/google_project_iam_bindings.md
+++ b/docs/resources/google_project_iam_bindings.md
@@ -38,7 +38,7 @@ The following examples show how to use this InSpec audit resource.
its('count') { should be <= 100}
end
-### Test that an expected iam_binding is available for the project
+### Test that an expected role is available for the project
describe google_project_iam_bindings(project: 'chef-inspec-gcp') do
its('iam_binding_roles') { should include "roles/storage.admin" }
diff --git a/libraries/google_kms_crypto_key.rb b/libraries/google_kms_crypto_key.rb
new file mode 100644
index 000000000..ed0d057f1
--- /dev/null
+++ b/libraries/google_kms_crypto_key.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'gcp_backend'
+require 'time'
+require 'google/apis/cloudkms_v1'
+
+module Inspec::Resources
+ class GoogleKMSCryptoKey < GcpResourceBase
+ name 'google_kms_crypto_key'
+ desc 'Verifies settings for a KMS key ring'
+
+ example "
+ describe google_kms_crypto_key(project: 'chef-inspec-gcp', location: 'us-east1', key_ring_name: 'key-ring', name: 'crypto-key') do
+ it { should exist }
+ end
+ "
+
+ def initialize(opts = {})
+ # Call the parent class constructor
+ super(opts)
+ @display_name = opts[:name]
+ catch_gcp_errors do
+ @kms_crypto_key = @gcp.gcp_client(Google::Apis::CloudkmsV1::CloudKMSService).get_project_location_key_ring_crypto_key("projects/#{opts[:project]}/locations/#{opts[:location]}/keyRings/#{opts[:key_ring_name]}/cryptoKeys/#{opts[:name]}")
+ create_resource_methods(@kms_crypto_key)
+ end
+ end
+
+ def crypto_key_name
+ return false if !defined?(name)
+ name.split('/').last
+ end
+
+ def create_time_date
+ return false if !defined?(create_time)
+ Time.parse(create_time)
+ end
+
+ # this is added for completeness as crypto key IAM bindings use the crypto_key_url as an identifier
+ def crypto_key_url
+ return false if !defined?(name)
+ name
+ end
+
+ def next_rotation_time_date
+ return false if !defined?(next_rotation_time)
+ Time.parse(next_rotation_time)
+ end
+
+ def primary_create_time_date
+ return false if !defined?(primary.create_time)
+ Time.parse(primary.create_time)
+ end
+
+ def primary_name
+ return false if !defined?(primary.name)
+ primary.name
+ end
+
+ def primary_state
+ return false if !defined?(primary.state)
+ primary.state
+ end
+
+ def exists?
+ !@kms_crypto_key.nil?
+ end
+
+ def to_s
+ "Crytpo Key #{@display_name}"
+ end
+ end
+end
diff --git a/libraries/google_kms_crypto_key_iam_binding.rb b/libraries/google_kms_crypto_key_iam_binding.rb
new file mode 100644
index 000000000..70975004e
--- /dev/null
+++ b/libraries/google_kms_crypto_key_iam_binding.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'gcp_backend'
+
+module Inspec::Resources
+ class GoogleKMSCryptoKeyIAMBinding < GcpResourceBase
+ name 'google_kms_crypto_key_iam_binding'
+ desc 'Verifies settings for a single KMS Crypto Key IAM binding'
+
+ example "
+ describe google_kms_crypto_key_iam_binding(crypto_key_url: 'projects/project/locations/europe-west2/keyRings/key-ring/cryptoKeys/key-name', role: 'roles/owner') do
+ it { should exist }
+ end
+ "
+
+ def initialize(opts = {})
+ # Call the parent class constructor
+ super(opts)
+ @crypto_key_url = opts[:crypto_key_url]
+ @role = opts[:role]
+ @iam_binding_exists = false
+ @members_list=[]
+ catch_gcp_errors do
+ # note this is the same call as for the plural iam_bindings resource because there isn't an easy way to pull out a singular binding
+ @iam_bindings = @gcp.gcp_client(Google::Apis::CloudkmsV1::CloudKMSService).get_project_location_key_ring_crypto_key_iam_policy(@crypto_key_url)
+ raise Inspec::Exceptions::ResourceFailed, "google_kms_crypto_key_iam_binding is missing expected IAM policy 'bindings' property" if !@iam_bindings || !@iam_bindings.bindings
+ @iam_bindings.bindings.each do |binding|
+ next if binding.role != @role
+ @iam_binding_exists=true
+ @members_list=binding.members
+ end
+ end
+ end
+
+ # return the list of users corresponding to the role
+ def members
+ @members_list
+ end
+
+ def exists?
+ @iam_binding_exists
+ end
+
+ def to_s
+ "Crypto Key IAM Binding #{@role}"
+ end
+ end
+end
diff --git a/libraries/google_kms_crypto_key_iam_bindings.rb b/libraries/google_kms_crypto_key_iam_bindings.rb
new file mode 100644
index 000000000..d7abb480e
--- /dev/null
+++ b/libraries/google_kms_crypto_key_iam_bindings.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'gcp_backend'
+
+module Inspec::Resources
+ class GoogleKMSCryptoKeyIAMBindings < GcpResourceBase
+ name 'google_kms_crypto_key_iam_bindings'
+ desc 'Verifies settings for GCP KMS Crypto Key IAM Bindings in bulk'
+
+ example "
+ describe google_kms_key_ring_iam_bindings(crypto_key_url: 'projects/project/locations/europe-west2/keyRings/key-ring/cryptoKeys/key-name') do
+ it { should exist }
+ end
+ "
+
+ def initialize(opts = {})
+ # Call the parent class constructor
+ super(opts)
+ @crypto_key_url = opts[:crypto_key_url]
+ end
+
+ # FilterTable setup
+ filter_table_config = FilterTable.create
+ filter_table_config.add(:iam_binding_roles, field: :iam_binding_role)
+ filter_table_config.connect(self, :fetch_data)
+
+ def fetch_data
+ iam_binding_rows = []
+ catch_gcp_errors do
+ @iam_bindings = @gcp.gcp_client(Google::Apis::CloudkmsV1::CloudKMSService).get_project_location_key_ring_crypto_key_iam_policy(@crypto_key_url)
+ end
+ return [] if !@iam_bindings || !@iam_bindings.bindings
+ @iam_bindings.bindings.map do |iam_binding|
+ iam_binding_rows+=[{ iam_binding_role: iam_binding.role }]
+ end
+ @table = iam_binding_rows
+ end
+ end
+end
diff --git a/libraries/google_kms_crypto_keys.rb b/libraries/google_kms_crypto_keys.rb
new file mode 100644
index 000000000..40d722d80
--- /dev/null
+++ b/libraries/google_kms_crypto_keys.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'gcp_backend'
+
+module Inspec::Resources
+ class GoogleKMSCryptoKeys < GcpResourceBase
+ name 'google_kms_crypto_keys'
+ desc 'Verifies settings for GCP KMS crypto keys in bulk'
+
+ example "
+ describe google_kms_crypto_keys(project: 'chef-inspec-gcp', location: 'us-east1', crypto_key_name: 'key-ring') do
+ it { should exist }
+ end
+ "
+
+ def initialize(opts = {})
+ # Call the parent class constructor
+ super(opts)
+ @project = opts[:project]
+ @location = opts[:location]
+ @key_ring_name = opts[:key_ring_name]
+ end
+
+ # FilterTable setup
+ filter_table_config = FilterTable.create
+ filter_table_config.add(:crypto_key_names, field: :crypto_key_name)
+ filter_table_config.add(:crypto_key_urls, field: :crypto_key_url)
+ filter_table_config.connect(self, :fetch_data)
+
+ def fetch_data
+ crypto_key_rows = []
+ catch_gcp_errors do
+ @crypto_keys = @gcp.gcp_client(Google::Apis::CloudkmsV1::CloudKMSService).list_project_location_key_ring_crypto_keys("projects/#{@project}/locations/#{@location}/keyRings/#{@key_ring_name}")
+ end
+ return [] if !@crypto_keys || !@crypto_keys.crypto_keys
+ @crypto_keys.crypto_keys.map do |crypto_key|
+ crypto_key_rows+=[{ crypto_key_name: crypto_key.name.split('/').last,
+ crypto_key_url: crypto_key.name }]
+ end
+ @table = crypto_key_rows
+ end
+ end
+end
diff --git a/libraries/google_kms_key_ring.rb b/libraries/google_kms_key_ring.rb
new file mode 100644
index 000000000..ef453b3ca
--- /dev/null
+++ b/libraries/google_kms_key_ring.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'gcp_backend'
+require 'time'
+require 'google/apis/cloudkms_v1'
+
+module Inspec::Resources
+ class GoogleKMSKeyRing < GcpResourceBase
+ name 'google_kms_key_ring'
+ desc 'Verifies settings for a KMS key ring'
+
+ example "
+ describe google_kms_key_ring(project: 'chef-inspec-gcp', location: 'us-east1', name: 'key-ring-name') do
+ it { should exist }
+ end
+ "
+
+ def initialize(opts = {})
+ # Call the parent class constructor
+ super(opts)
+ @display_name = opts[:name]
+ catch_gcp_errors do
+ @kms_key_ring = @gcp.gcp_client(Google::Apis::CloudkmsV1::CloudKMSService).get_project_location_key_ring("projects/#{opts[:project]}/locations/#{opts[:location]}/keyRings/#{opts[:name]}")
+ create_resource_methods(@kms_key_ring)
+ end
+ end
+
+ def key_ring_name
+ return false if !defined?(name)
+ name.split('/').last
+ end
+
+ def create_time_date
+ return false if !defined?(create_time)
+ Time.parse(create_time)
+ end
+
+ # this is added for completeness as key ring IAM bindings use the key_ring_url as an identifier
+ def key_ring_url
+ return false if !defined?(name)
+ name
+ end
+
+ def exists?
+ !@kms_key_ring.nil?
+ end
+
+ def to_s
+ "Key Ring #{@display_name}"
+ end
+ end
+end
diff --git a/libraries/google_kms_key_ring_iam_binding.rb b/libraries/google_kms_key_ring_iam_binding.rb
new file mode 100644
index 000000000..931c063fb
--- /dev/null
+++ b/libraries/google_kms_key_ring_iam_binding.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'gcp_backend'
+
+module Inspec::Resources
+ class GoogleKMSKeyRingIAMBinding < GcpResourceBase
+ name 'google_kms_key_ring_iam_binding'
+ desc 'Verifies settings for a single KMS Key Ring IAM binding'
+
+ example "
+ describe google_kms_key_ring_iam_binding(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring', role: 'roles/compute.admin') do
+ it { should exist }
+ its('members') {should include 'user:someuser@domain.com' }
+ end
+ "
+
+ def initialize(opts = {})
+ # Call the parent class constructor
+ super(opts)
+ @key_ring_url = opts[:key_ring_url]
+ @role = opts[:role]
+ @iam_binding_exists = false
+ @members_list=[]
+ catch_gcp_errors do
+ # note this is the same call as for the plural iam_bindings resource because there isn't an easy way to pull out a singular binding
+ @iam_bindings = @gcp.gcp_client(Google::Apis::CloudkmsV1::CloudKMSService).get_project_location_key_ring_iam_policy(@key_ring_url)
+ raise Inspec::Exceptions::ResourceFailed, "google_kms_key_ring_iam_binding is missing expected IAM policy 'bindings' property" if !@iam_bindings || !@iam_bindings.bindings
+ @iam_bindings.bindings.each do |binding|
+ next if binding.role != @role
+ @iam_binding_exists=true
+ @members_list=binding.members
+ end
+ end
+ end
+
+ # return the list of users corresponding to the role
+ def members
+ @members_list
+ end
+
+ def exists?
+ @iam_binding_exists
+ end
+
+ def to_s
+ "Key Ring IAM Binding #{@role}"
+ end
+ end
+end
diff --git a/libraries/google_kms_key_ring_iam_bindings.rb b/libraries/google_kms_key_ring_iam_bindings.rb
new file mode 100644
index 000000000..16a85a676
--- /dev/null
+++ b/libraries/google_kms_key_ring_iam_bindings.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'gcp_backend'
+
+module Inspec::Resources
+ class GoogleKMSKeyRingIAMBindings < GcpResourceBase
+ name 'google_kms_key_ring_iam_bindings'
+ desc 'Verifies settings for GCP KMS key ring IAM bindings in bulk'
+
+ example "
+ describe google_kms_key_ring_iam_bindings(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring') do
+ it { should exist }
+ end
+ "
+
+ def initialize(opts = {})
+ # Call the parent class constructor
+ super(opts)
+ @key_ring_url = opts[:key_ring_url]
+ end
+
+ # FilterTable setup
+ filter_table_config = FilterTable.create
+ filter_table_config.add(:iam_binding_roles, field: :iam_binding_role)
+ filter_table_config.connect(self, :fetch_data)
+
+ def fetch_data
+ iam_binding_rows = []
+ catch_gcp_errors do
+ @iam_bindings = @gcp.gcp_client(Google::Apis::CloudkmsV1::CloudKMSService).get_project_location_key_ring_iam_policy(@key_ring_url)
+ end
+ return [] if !@iam_bindings || !@iam_bindings.bindings
+ @iam_bindings.bindings.map do |iam_binding|
+ iam_binding_rows+=[{ iam_binding_role: iam_binding.role }]
+ end
+ @table = iam_binding_rows
+ end
+ end
+end
diff --git a/libraries/google_kms_key_rings.rb b/libraries/google_kms_key_rings.rb
new file mode 100644
index 000000000..96322268f
--- /dev/null
+++ b/libraries/google_kms_key_rings.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'gcp_backend'
+
+module Inspec::Resources
+ class GoogleKMSKeyRings < GcpResourceBase
+ name 'google_kms_key_rings'
+ desc 'Verifies settings for GCP KMS key rings in bulk'
+
+ example "
+ describe google_kms_key_rings(project: 'chef-inspec-gcp', location: 'us-east1') do
+ it { should exist }
+ ...
+ end
+ "
+
+ def initialize(opts = {})
+ # Call the parent class constructor
+ super(opts)
+ @project = opts[:project]
+ @location = opts[:location]
+ end
+
+ # FilterTable setup
+ filter_table_config = FilterTable.create
+ filter_table_config.add(:key_ring_names, field: :key_ring_name)
+ filter_table_config.add(:key_ring_urls, field: :key_ring_url)
+ filter_table_config.connect(self, :fetch_data)
+
+ def fetch_data
+ key_ring_rows = []
+ catch_gcp_errors do
+ @key_rings = @gcp.gcp_client(Google::Apis::CloudkmsV1::CloudKMSService).list_project_location_key_rings("projects/#{@project}/locations/#{@location}")
+ end
+ return [] if !@key_rings || !@key_rings.key_rings
+ @key_rings.key_rings.map do |key_ring|
+ key_ring_rows+=[{ key_ring_name: key_ring.name.split('/').last,
+ key_ring_url: key_ring.name }]
+ end
+ @table = key_ring_rows
+ end
+ end
+end
diff --git a/libraries/google_project_iam_binding.rb b/libraries/google_project_iam_binding.rb
index 49c369dbd..cc7d3c605 100644
--- a/libraries/google_project_iam_binding.rb
+++ b/libraries/google_project_iam_binding.rb
@@ -5,19 +5,17 @@
module Inspec::Resources
class GoogleProjectIAMBinding < GcpResourceBase
name 'google_project_iam_binding'
- desc 'Verifies settings for a single project IAM binding'
+ desc 'Verifies settings for a single GCP KMS key ring IAM bindings'
example "
- describe google_project_iam_binding(project: 'chef-inspec-gcp', role: 'roles/compute.admin') do
+ describe google_kms_key_ring_iam_binding(key_ring_url: 'projects/project/locations/europe-west2/keyRings/key-ring', role: 'roles/compute.admin') do
it { should exist }
- its('members') {should include 'user:someuser@domain.com' }
end
"
def initialize(opts = {})
# Call the parent class constructor
super(opts)
- @display_name = opts[:name]
@project = opts[:project]
@role = opts[:role]
@iam_binding_exists = false
@@ -44,7 +42,7 @@ def exists?
end
def to_s
- "Project IAM Binding #{@display_name}"
+ "Project IAM Binding #{@role}"
end
end
end
diff --git a/test/integration/build/gcp.tf b/test/integration/build/gcp.tf
index 02b3ce1e9..6b037f20e 100644
--- a/test/integration/build/gcp.tf
+++ b/test/integration/build/gcp.tf
@@ -58,11 +58,17 @@ variable "gcp_kube_cluster_zone_extra2" {}
variable "gcp_kube_cluster_master_user" {}
variable "gcp_kube_cluster_master_pass" {}
+variable "gcp_kms_key_ring_policy_name" {}
+variable "gcp_kms_key_ring_binding_member_name" {}
+variable "gcp_kms_crypto_key_name_policy" {}
+variable "gcp_kms_crypto_key_name_binding" {}
variable "gcp_storage_bucket_name" {
default ="gcp-inspec"
}
+#variable "gcp_inspec_user_email" {}
+
variable "gcp_enable_privileged_resources" {}
provider "google" {
@@ -411,4 +417,98 @@ output "cluster_ca_certificate" {
##############################################################
# End of the GKE cluster example
-##############################################################
\ No newline at end of file
+##############################################################
+
+# Start GCP KMS resources
+# This reuses service account email address that was created earlier to test IAM policies/binding/memberships
+
+#Note: google_kms_key_ring_iam_policy cannot be used in conjunction with google_kms_key_ring_iam_binding and google_kms_key_ring_iam_member or they will fight over what your policy should be.
+
+resource "google_kms_key_ring" "gcp_kms_key_ring_policy" {
+ count = "${var.gcp_enable_privileged_resources}"
+ project = "${var.gcp_project_id}"
+ name = "${var.gcp_kms_key_ring_policy_name}"
+ location = "${var.gcp_location}"
+}
+
+
+#Note: google_kms_key_ring_iam_binding resources can be used in conjunction with google_kms_key_ring_iam_member resources only if they do not grant privilege to the same role.
+
+resource "google_kms_key_ring" "gcp_kms_key_ring_binding_member" {
+ count = "${var.gcp_enable_privileged_resources}"
+ project = "${var.gcp_project_id}"
+ name = "${var.gcp_kms_key_ring_binding_member_name}"
+ location = "${var.gcp_location}"
+}
+
+# Use the first key ring to attach an IAM policy
+
+data "google_iam_policy" "gcp_inspec_admin_key_ring" {
+ count = "${var.gcp_enable_privileged_resources}"
+ binding {
+ role = "roles/editor"
+
+ members = [
+ "serviceAccount:${google_service_account.generic_service_account_object_viewer.email}",
+ ]
+ }
+}
+
+resource "google_kms_key_ring_iam_policy" "key_ring_policy" {
+ count = "${var.gcp_enable_privileged_resources}"
+ key_ring_id = "${google_kms_key_ring.gcp_kms_key_ring_policy.id}"
+ policy_data = "${data.google_iam_policy.gcp_inspec_admin_key_ring.policy_data}"
+}
+
+# Use the second key ring to attach an IAM binding plus IAM member affecting different roles
+
+resource "google_kms_key_ring_iam_binding" "key_ring_binding" {
+ count = "${var.gcp_enable_privileged_resources}"
+ key_ring_id = "${google_kms_key_ring.gcp_kms_key_ring_binding_member.id}"
+ role = "roles/editor"
+
+ members = [
+ "serviceAccount:${google_service_account.generic_service_account_object_viewer.email}",
+ ]
+}
+
+resource "google_kms_key_ring_iam_member" "key_ring_iam_member" {
+ count = "${var.gcp_enable_privileged_resources}"
+ key_ring_id = "${google_kms_key_ring.gcp_kms_key_ring_binding_member.id}"
+ role = "roles/owner"
+ member = "serviceAccount:${google_service_account.generic_service_account_object_viewer.email}"
+}
+
+resource "google_kms_crypto_key" "crypto_key_policy" {
+ count = "${var.gcp_enable_privileged_resources}"
+ name = "${var.gcp_kms_crypto_key_name_policy}"
+ key_ring = "${google_kms_key_ring.gcp_kms_key_ring_policy.id}"
+ rotation_period = "100000s"
+}
+
+resource "google_kms_crypto_key" "crypto_key_binding" {
+ count = "${var.gcp_enable_privileged_resources}"
+ name = "${var.gcp_kms_crypto_key_name_binding}"
+ key_ring = "${google_kms_key_ring.gcp_kms_key_ring_binding_member.id}"
+ rotation_period = "100000s"
+}
+
+resource "google_kms_crypto_key_iam_member" "crypto_key_iam_member" {
+ count = "${var.gcp_enable_privileged_resources}"
+ crypto_key_id = "${google_kms_crypto_key.crypto_key_policy.id}"
+ role = "roles/editor"
+ member = "serviceAccount:${google_service_account.generic_service_account_object_viewer.email}"
+}
+
+resource "google_kms_crypto_key_iam_binding" "crypto_key_iam_binding" {
+ count = "${var.gcp_enable_privileged_resources}"
+ crypto_key_id = "${google_kms_crypto_key.crypto_key_binding.id}"
+ role = "roles/editor"
+
+ members = [
+ "serviceAccount:${google_service_account.generic_service_account_object_viewer.email}",
+ ]
+}
+
+
+# End GCP KMS resources
\ No newline at end of file
diff --git a/test/integration/configuration/gcp_inspec_config.rb b/test/integration/configuration/gcp_inspec_config.rb
index f8c391b56..bb584c5ce 100644
--- a/test/integration/configuration/gcp_inspec_config.rb
+++ b/test/integration/configuration/gcp_inspec_config.rb
@@ -60,6 +60,11 @@ module GCPInspecConfig
:gcp_kube_cluster_master_user => "gcp-inspec-kube-admin",
:gcp_kube_cluster_master_pass => Passgen::generate(length: 20, uppercase: true, lowercase: true, symbols: true, digits: true),
:gcp_kube_nodepool_name => "default-pool",
+ :gcp_inspec_user_email => "user:chef@example.com",
+ :gcp_kms_key_ring_policy_name => "gcp-inspec-kms-key-ring-#{(0...15).map { (65 + rand(26)).chr }.join.downcase}",
+ :gcp_kms_key_ring_binding_member_name => "gcp-inspec-kms-key-ring-#{(0...15).map { (65 + rand(26)).chr }.join.downcase}",
+ :gcp_kms_crypto_key_name_policy => "gcp-inspec-kms-crypto-key-policy-#{(0...15).map { (65 + rand(26)).chr }.join.downcase}",
+ :gcp_kms_crypto_key_name_binding => "gcp-inspec-kms-crypto-key-binding-#{(0...15).map { (65 + rand(26)).chr }.join.downcase}",
# Some resources require elevated privileges to create and therefore test against. The below flag is used to control
# both the terraform resource creation and the inspec test execution for those resources. Default behaviour is for this to
# be disabled meaning a user needs no special GCP privileges to run the integration test pack.
diff --git a/test/integration/verify/controls/google_kms_crypto_key.rb b/test/integration/verify/controls/google_kms_crypto_key.rb
new file mode 100644
index 000000000..dd66d5c1f
--- /dev/null
+++ b/test/integration/verify/controls/google_kms_crypto_key.rb
@@ -0,0 +1,24 @@
+title 'Test single GCP KMS Crypto Key'
+
+gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
+gcp_kms_key_ring_policy_name = attribute(:gcp_kms_key_ring_policy_name,default:'',description:'GCP key ring name to test against.')
+gcp_location = attribute(:gcp_location, default: '', description: 'The GCP region being used.')
+gcp_kms_crypto_key_name_policy = attribute(:gcp_kms_crypto_key_name_policy, default: '', description: 'The GCP cryto key name.')
+gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources,default:0,description:'Flag to enable privileged resources requiring elevated privileges in GCP.')
+
+control 'gcp-kms-crypto-key-1.0' do
+
+ only_if { gcp_enable_privileged_resources.to_i == 1 }
+ impact 1.0
+ title 'Ensure single GCP KMS Crypto Key has the correct properties.'
+
+ describe google_kms_crypto_key(project: gcp_project_id, location: gcp_location, key_ring_name: gcp_kms_key_ring_policy_name, name: gcp_kms_crypto_key_name_policy) do
+ it { should exist }
+ its('create_time_date') { should be > Time.now - 365*60*60*24*10 }
+ its('crypto_key_name'){ should eq gcp_kms_crypto_key_name_policy }
+ its('primary_state') { should eq "ENABLED" }
+ its('purpose') { should eq "ENCRYPT_DECRYPT" }
+ its('next_rotation_time_date') { should be > Time.now - 100000 }
+ its('create_time_date') { should be > Time.now - 365*60*60*24*10 }
+ end
+end
\ No newline at end of file
diff --git a/test/integration/verify/controls/google_kms_crypto_key_iam_binding.rb b/test/integration/verify/controls/google_kms_crypto_key_iam_binding.rb
new file mode 100644
index 000000000..a7191659c
--- /dev/null
+++ b/test/integration/verify/controls/google_kms_crypto_key_iam_binding.rb
@@ -0,0 +1,27 @@
+title 'GCP KMS Crypto Key IAM Binding Properties'
+
+gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
+gcp_location = attribute(:gcp_location, default: '', description: 'The GCP region being used.')
+gcp_kms_key_ring_policy_name = attribute(:gcp_kms_key_ring_policy_name,default:'',description:'GCP key ring name to test against.')
+gcp_kms_crypto_key_name_policy = attribute(:gcp_kms_crypto_key_name_policy, default: '', description: 'The GCP cryto key name.')
+gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources,default:0,description:'Flag to enable privileged resources requiring elevated privileges in GCP.')
+gcp_kms_crypto_key_name_binding = attribute(:gcp_kms_crypto_key_name_binding,default:'',description:'GCP key ring name to test against.')
+gcp_kms_key_ring_binding_member_name = attribute(:gcp_kms_key_ring_binding_member_name, default: '', description: 'The GCP cryto key name.')
+
+
+control 'gcp-crypto-key-iam-binding-1.0' do
+
+ only_if { gcp_enable_privileged_resources.to_i == 1 }
+ impact 1.0
+ title 'Ensure single KMS Crypto Key IAM Binding has the correct properties'
+
+ describe google_kms_crypto_key_iam_binding(crypto_key_url: "projects/#{gcp_project_id}/locations/#{gcp_location}/keyRings/#{gcp_kms_key_ring_binding_member_name}/cryptoKeys/#{gcp_kms_crypto_key_name_binding}", role: "roles/editor") do
+ it { should exist }
+ its('members.count') { should eq 1}
+ end
+
+ describe google_kms_crypto_key_iam_binding(crypto_key_url: "projects/#{gcp_project_id}/locations/#{gcp_location}/keyRings/#{gcp_kms_key_ring_policy_name}/cryptoKeys/#{gcp_kms_crypto_key_name_policy}", role: "roles/editor") do
+ it { should exist }
+ its('members.count') { should eq 1}
+ end
+end
\ No newline at end of file
diff --git a/test/integration/verify/controls/google_kms_crypto_key_iam_bindings.rb b/test/integration/verify/controls/google_kms_crypto_key_iam_bindings.rb
new file mode 100644
index 000000000..78dc31712
--- /dev/null
+++ b/test/integration/verify/controls/google_kms_crypto_key_iam_bindings.rb
@@ -0,0 +1,20 @@
+title 'GCP KMS Crypto Key IAM Bindings Properties'
+
+gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
+gcp_location = attribute(:gcp_location, default: '', description: 'The GCP region being used.')
+gcp_kms_key_ring_binding_member_name = attribute(:gcp_kms_key_ring_binding_member_name,default:'',description:'GCP key ring name to test against.')
+gcp_kms_crypto_key_name_binding = attribute(:gcp_kms_crypto_key_name_binding,default:'',description:'Key in key ring to test.')
+gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources,default:0,description:'Flag to enable privileged resources requiring elevated privileges in GCP.')
+
+control 'gcp-kms-crypto-key-iam-bindings-1.0' do
+
+ only_if { gcp_enable_privileged_resources.to_i == 1 }
+ impact 1.0
+ title 'Ensure GCP KMS Crypto Key IAM Bindings have the correct properties in bulk'
+
+ describe google_kms_crypto_key_iam_bindings(crypto_key_url: "projects/#{gcp_project_id}/locations/#{gcp_location}/keyRings/#{gcp_kms_key_ring_binding_member_name}/cryptoKeys/#{gcp_kms_crypto_key_name_binding}") do
+ it { should exist }
+ its('count') { should be <= 100}
+ its('iam_binding_roles') { should include "roles/editor" }
+ end
+end
\ No newline at end of file
diff --git a/test/integration/verify/controls/google_kms_crypto_keys.rb b/test/integration/verify/controls/google_kms_crypto_keys.rb
new file mode 100644
index 000000000..a6c51dabd
--- /dev/null
+++ b/test/integration/verify/controls/google_kms_crypto_keys.rb
@@ -0,0 +1,29 @@
+title 'GCP KMS Crypto Keys Properties'
+
+gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
+gcp_location = attribute(:gcp_location, default: '', description: 'The GCP region being used.')
+gcp_kms_key_ring_policy_name = attribute(:gcp_kms_key_ring_policy_name,default:'',description:'GCP key ring name to test against.')
+gcp_kms_crypto_key_name_policy = attribute(:gcp_kms_crypto_key_name_policy, default: '', description: 'The GCP cryto key name.')
+gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources,default:0,description:'Flag to enable privileged resources requiring elevated privileges in GCP.')
+gcp_kms_crypto_key_name_binding = attribute(:gcp_kms_crypto_key_name_binding,default:'',description:'GCP key ring name to test against.')
+gcp_kms_key_ring_binding_member_name = attribute(:gcp_kms_key_ring_binding_member_name, default: '', description: 'The GCP cryto key name.')
+
+
+control 'gcp-crypto-keys-1.0' do
+
+ only_if { gcp_enable_privileged_resources.to_i == 1 }
+ impact 1.0
+ title 'Ensure KMS crypto keys have the correct properties in bulk'
+
+ describe google_kms_crypto_keys(project: gcp_project_id, location: gcp_location, key_ring_name: gcp_kms_key_ring_policy_name) do
+ it { should exist }
+ its('count') { should eq 1}
+ its ('crypto_key_names') { should include gcp_kms_crypto_key_name_policy }
+ end
+
+ describe google_kms_crypto_keys(project: gcp_project_id, location: gcp_location, key_ring_name: gcp_kms_key_ring_binding_member_name) do
+ it { should exist }
+ its('count') { should eq 1}
+ its ('crypto_key_names') { should include gcp_kms_crypto_key_name_binding }
+ end
+end
\ No newline at end of file
diff --git a/test/integration/verify/controls/google_kms_key_ring.rb b/test/integration/verify/controls/google_kms_key_ring.rb
new file mode 100644
index 000000000..298e9a922
--- /dev/null
+++ b/test/integration/verify/controls/google_kms_key_ring.rb
@@ -0,0 +1,19 @@
+title 'Test single GCP KMS Key Ring'
+
+gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
+gcp_location = attribute(:gcp_location, default: '', description: 'The GCP region being used.')
+gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources,default:0,description:'Flag to enable privileged resources requiring elevated privileges in GCP.')
+gcp_kms_key_ring_policy_name = attribute(:gcp_kms_key_ring_policy_name,default:'',description:'GCP key ring name to test against.')
+
+control 'gcp-key-ring-1.0' do
+
+ only_if { gcp_enable_privileged_resources.to_i == 1 }
+ impact 1.0
+ title 'Ensure single KMS Key Ring has the correct properties.'
+
+ describe google_kms_key_ring(project: gcp_project_id, location: gcp_location, name: gcp_kms_key_ring_policy_name) do
+ it { should exist }
+ its('create_time_date') { should be > Time.now - 365*60*60*24*10 }
+ its('key_ring_name'){ should eq gcp_kms_key_ring_policy_name }
+ end
+end
\ No newline at end of file
diff --git a/test/integration/verify/controls/google_kms_key_ring_iam_binding.rb b/test/integration/verify/controls/google_kms_key_ring_iam_binding.rb
new file mode 100644
index 000000000..b8aa86f00
--- /dev/null
+++ b/test/integration/verify/controls/google_kms_key_ring_iam_binding.rb
@@ -0,0 +1,29 @@
+title 'Test single GCP KMS Key Ring IAM Binding'
+
+gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
+gcp_kms_key_ring_policy_name = attribute(:gcp_kms_key_ring_policy_name,default:'',description:'GCP key ring name to test against.')
+gcp_kms_key_ring_binding_member_name = attribute(:gcp_kms_key_ring_binding_member_name,default:'',description:'GCP key ring name to test against.')
+gcp_location = attribute(:gcp_location, default: '', description: 'The GCP region being used.')
+gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources,default:0,description:'Flag to enable privileged resources requiring elevated privileges in GCP.')
+
+control 'gcp-kms-key-ring-iam-binding-1.0' do
+
+ only_if { gcp_enable_privileged_resources.to_i == 1 }
+ impact 1.0
+ title 'Ensure single GCP GCP KMS Key Ring IAM bindings have the correct properties. Examples below include attaching an IAM policy, binding and member to a key ring.'
+
+ describe google_kms_key_ring_iam_binding(key_ring_url: "projects/#{gcp_project_id}/locations/#{gcp_location}/keyRings/#{gcp_kms_key_ring_policy_name}", role: "roles/editor") do
+ it { should exist }
+ its ('members.count'){ should eq 1 }
+ end
+
+ describe google_kms_key_ring_iam_binding(key_ring_url: "projects/#{gcp_project_id}/locations/#{gcp_location}/keyRings/#{gcp_kms_key_ring_binding_member_name}", role: "roles/editor") do
+ it { should exist }
+ its ('members.count'){ should eq 1 }
+ end
+
+ describe google_kms_key_ring_iam_binding(key_ring_url: "projects/#{gcp_project_id}/locations/#{gcp_location}/keyRings/#{gcp_kms_key_ring_binding_member_name}", role: "roles/owner") do
+ it { should exist }
+ its ('members.count'){ should eq 1 }
+ end
+end
\ No newline at end of file
diff --git a/test/integration/verify/controls/google_kms_key_ring_iam_bindings.rb b/test/integration/verify/controls/google_kms_key_ring_iam_bindings.rb
new file mode 100644
index 000000000..c6ffbbbc0
--- /dev/null
+++ b/test/integration/verify/controls/google_kms_key_ring_iam_bindings.rb
@@ -0,0 +1,20 @@
+title 'GCP KMS Key Ring IAM Binding Properties'
+
+gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
+gcp_location = attribute(:gcp_location, default: '', description: 'The GCP region being used.')
+gcp_kms_key_ring_binding_member_name = attribute(:gcp_kms_key_ring_binding_member_name,default:'',description:'GCP key ring name to test against.')
+gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources,default:0,description:'Flag to enable privileged resources requiring elevated privileges in GCP.')
+
+control 'gcp-kms-key-ring-iam-bindings-1.0' do
+
+ only_if { gcp_enable_privileged_resources.to_i == 1 }
+ impact 1.0
+ title 'Ensure GCP KMS Key Ring IAM bindings have the correct properties in bulk'
+
+ describe google_kms_key_ring_iam_bindings(key_ring_url: "projects/#{gcp_project_id}/locations/#{gcp_location}/keyRings/#{gcp_kms_key_ring_binding_member_name}") do
+ it { should exist }
+ its('count') { should be <= 100}
+ its('iam_binding_roles') { should include "roles/owner" }
+ its('iam_binding_roles') { should include "roles/editor" }
+ end
+end
\ No newline at end of file
diff --git a/test/integration/verify/controls/google_kms_key_rings.rb b/test/integration/verify/controls/google_kms_key_rings.rb
new file mode 100644
index 000000000..2556317bd
--- /dev/null
+++ b/test/integration/verify/controls/google_kms_key_rings.rb
@@ -0,0 +1,21 @@
+title 'GCP KMS Key Rings Properties'
+
+gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
+gcp_location = attribute(:gcp_location, default: '', description: 'The GCP region being used.')
+gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources,default:0,description:'Flag to enable privileged resources requiring elevated privileges in GCP.')
+gcp_kms_key_ring_policy_name = attribute(:gcp_kms_key_ring_policy_name,default:'',description:'GCP key ring name to test against.')
+gcp_kms_key_ring_binding_member_name = attribute(:gcp_kms_key_ring_binding_member_name,default:'',description:'GCP key ring name to test against.')
+
+control 'gcp-key-rings-1.0' do
+
+ only_if { gcp_enable_privileged_resources.to_i == 1 }
+ impact 1.0
+ title 'Ensure KMS key rings have the correct properties in bulk'
+
+ describe google_kms_key_rings(project: gcp_project_id, location: gcp_location) do
+ it { should exist }
+ its ('key_ring_names') { should include gcp_kms_key_ring_policy_name }
+ its ('key_ring_names') { should include gcp_kms_key_ring_binding_member_name }
+ end
+
+end
\ No newline at end of file