From 1e5067d62af4ed89c82b65220e3ee8e09e6eefe9 Mon Sep 17 00:00:00 2001 From: Sam Levenick Date: Thu, 9 Jan 2020 16:32:11 -0800 Subject: [PATCH] Inspec kms generated (#2945) Merged PR #2945. --- build/ansible | 2 +- build/inspec | 2 +- overrides/inspec/resource_override.rb | 5 +- products/kms/api.yaml | 14 +++++- products/kms/inspec.yaml | 47 +++++++++++++++++++ products/kms/terraform.yaml | 6 ++- .../attributes/external_attributes.yml | 4 +- .../google_kms_crypto_key.erb | 16 +++++++ .../google_kms_crypto_key_attributes.erb | 5 ++ .../google_kms_crypto_keys.erb | 8 ++++ .../google_kms_key_ring.erb | 13 +++++ .../google_kms_key_ring_attributes.erb | 4 ++ .../google_kms_key_rings.erb | 14 ++++++ templates/inspec/iam_policy/iam_policy.erb | 8 ++++ templates/inspec/plural_resource.erb | 3 ++ .../custom_functions/kms_crypto_key.erb | 3 ++ .../inspec/custom_functions/kms_key_ring.erb | 3 ++ .../custom_functions/kms_key_ring_name.erb | 1 + 18 files changed, 150 insertions(+), 8 deletions(-) create mode 100644 products/kms/inspec.yaml create mode 100644 templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_key.erb create mode 100644 templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_key_attributes.erb create mode 100644 templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_keys.erb create mode 100644 templates/inspec/examples/google_kms_key_ring/google_kms_key_ring.erb create mode 100644 templates/inspec/examples/google_kms_key_ring/google_kms_key_ring_attributes.erb create mode 100644 templates/inspec/examples/google_kms_key_ring/google_kms_key_rings.erb create mode 100644 third_party/inspec/custom_functions/kms_crypto_key.erb create mode 100644 third_party/inspec/custom_functions/kms_key_ring.erb create mode 100644 third_party/inspec/custom_functions/kms_key_ring_name.erb diff --git a/build/ansible b/build/ansible index d18229763898..344b0d5acc56 160000 --- a/build/ansible +++ b/build/ansible @@ -1 +1 @@ -Subproject commit d182297638980d04e899e341297b31538533b8fb +Subproject commit 344b0d5acc56063ba834f4f021862497dc1db235 diff --git a/build/inspec b/build/inspec index c62a136cbceb..345148bd3bb1 160000 --- a/build/inspec +++ b/build/inspec @@ -1 +1 @@ -Subproject commit c62a136cbceb0bb6eec5a2d8cc6170c9262fe6b8 +Subproject commit 345148bd3bb15e9cc604a9f1c6f96edab1f89632 diff --git a/overrides/inspec/resource_override.rb b/overrides/inspec/resource_override.rb index dd4f285874f6..394f69189bf3 100644 --- a/overrides/inspec/resource_override.rb +++ b/overrides/inspec/resource_override.rb @@ -26,7 +26,7 @@ def self.attributes privileged singular_only singular_extra_examples - iam_binding + plural_custom_logic ] end @@ -43,6 +43,9 @@ def validate check :singular_only, type: :boolean, default: false # Points to a markdown file with extra examples to include in documentation check :singular_extra_examples, type: String + # Custom logic injected into plural resource's parse method. + # Allows for multiple interpretations of a single field within an API response + check :plural_custom_logic, type: String end end end diff --git a/products/kms/api.yaml b/products/kms/api.yaml index 5c80633000a0..d81ab71b4159 100644 --- a/products/kms/api.yaml +++ b/products/kms/api.yaml @@ -47,11 +47,16 @@ objects: The resource name for the KeyRing. required: true - !ruby/object:Api::Type::Time - name: 'creationTime' + name: 'createTime' description: | The time that this resource was created on the server. This is in RFC3339 text format. output: true + - !ruby/object:Api::Type::String + name: 'keyRingUrl' + description: | + The full resource name for the KeyRing + exclude: true references: !ruby/object:Api::Resource::ReferenceLinks guides: 'Creating a key ring': @@ -84,7 +89,7 @@ objects: input: true url_param_only: true - !ruby/object:Api::Type::Time - name: 'creationTime' + name: 'createTime' description: | The time that this resource was created on the server. This is in RFC3339 text format. @@ -131,6 +136,11 @@ objects: - "SOFTWARE" - "HSM" input: true + - !ruby/object:Api::Type::Time + name: 'nextRotationTime' + description: | + The time when KMS will create a new version of this Crypto Key. + output: true references: !ruby/object:Api::Resource::ReferenceLinks guides: 'Creating a key': diff --git a/products/kms/inspec.yaml b/products/kms/inspec.yaml new file mode 100644 index 000000000000..6d9ac52b224e --- /dev/null +++ b/products/kms/inspec.yaml @@ -0,0 +1,47 @@ +# Copyright 2020 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Provider::Inspec::Config +overrides: !ruby/object:Overrides::ResourceOverrides + KeyRing: !ruby/object:Overrides::Inspec::ResourceOverride + privileged: true + additional_functions: third_party/inspec/custom_functions/kms_key_ring.erb + plural_custom_logic: third_party/inspec/custom_functions/kms_key_ring_name.erb + properties: + name: !ruby/object:Overrides::Inspec::PropertyOverride + # This is added back via custom methods + exclude: true + keyRingUrl: !ruby/object:Overrides::Inspec::PropertyOverride + # Allows us to use the `name` field as the full URL + exclude: false + api_name: name + iam_policy: !ruby/object:Api::Resource::IamPolicy + base_url: 'projects/{{project}}/locations/{{location}}/keyRings/{{key_ring_name}}' + exclude: false + method_name_separator: ':' + CryptoKey: !ruby/object:Overrides::Inspec::ResourceOverride + base_url: 'projects/{{project}}/locations/{{location}}/keyRings/{{key_ring_name}}/cryptoKeys' + self_link: 'projects/{{project}}/locations/{{location}}/keyRings/{{key_ring_name}}/cryptoKeys/{{name}}' + privileged: true + additional_functions: third_party/inspec/custom_functions/kms_crypto_key.erb + properties: + name: !ruby/object:Overrides::Inspec::PropertyOverride + name: cryptoKeyName + api_name: name + name_from_self_link: true + iam_policy: !ruby/object:Api::Resource::IamPolicy + base_url: 'projects/{{project}}/locations/{{location}}/keyRings/{{key_ring_name}}/cryptoKeys/{{crypto_key_name}}' + exclude: false + method_name_separator: ':' + SecretCiphertext: !ruby/object:Overrides::Inspec::ResourceOverride + exclude: true \ No newline at end of file diff --git a/products/kms/terraform.yaml b/products/kms/terraform.yaml index ba4c9cf33dcb..d562ee246c9d 100644 --- a/products/kms/terraform.yaml +++ b/products/kms/terraform.yaml @@ -37,7 +37,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides attributes: | * `self_link`: The self link of the created KeyRing in the format `projects/{project}/locations/{location}/keyRings/{name}` properties: - creationTime: !ruby/object:Overrides::Terraform::PropertyOverride + createTime: !ruby/object:Overrides::Terraform::PropertyOverride exclude: true location: !ruby/object:Overrides::Terraform::PropertyOverride ignore_read: true @@ -74,7 +74,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides attributes: | * `self_link`: The self link of the created CryptoKey. Its format is `{{key_ring}}/cryptoKeys/{{name}}`. properties: - creationTime: !ruby/object:Overrides::Terraform::PropertyOverride + createTime: !ruby/object:Overrides::Terraform::PropertyOverride exclude: true keyRing: !ruby/object:Overrides::Terraform::PropertyOverride diff_suppress_func: 'kmsCryptoKeyRingsEquivalent' @@ -93,6 +93,8 @@ overrides: !ruby/object:Overrides::ResourceOverrides - "versionTemplate.algorithm" versionTemplate.protectionLevel: !ruby/object:Overrides::Terraform::PropertyOverride default_value: :SOFTWARE + nextRotationTime: !ruby/object:Overrides::Terraform::PropertyOverride + exclude: true custom_code: !ruby/object:Provider::Terraform::CustomCode custom_delete: templates/terraform/custom_delete/kms_crypto_key.erb custom_import: templates/terraform/custom_import/kms_crypto_key.go.erb diff --git a/templates/inspec/examples/attributes/external_attributes.yml b/templates/inspec/examples/attributes/external_attributes.yml index b954d3db3b34..f003d54e109d 100644 --- a/templates/inspec/examples/attributes/external_attributes.yml +++ b/templates/inspec/examples/attributes/external_attributes.yml @@ -20,4 +20,6 @@ gcp_kube_cluster_master_user: gcp-inspec-kube-admin gcp_kube_cluster_master_pass: P@$$w0rD gcp_storage_bucket_acl: storage-bucket-name gcp_storage_bucket_object_name: image1 -gcp_storage_bucket_object: bucket-with-object \ No newline at end of file +gcp_storage_bucket_object: bucket-with-object +gcp_kms_key_ring_policy_name: kms-key-ring +gcp_kms_crypto_key_name_policy: kms-key \ No newline at end of file diff --git a/templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_key.erb b/templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_key.erb new file mode 100644 index 000000000000..900a5bd51281 --- /dev/null +++ b/templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_key.erb @@ -0,0 +1,16 @@ +<% gcp_project_id = "#{external_attribute('gcp_project_id', doc_generation)}" -%> +<% gcp_location = "#{external_attribute('gcp_location', doc_generation)}" -%> +<% gcp_kms_key_ring_policy_name = "#{external_attribute('gcp_kms_key_ring_policy_name', doc_generation)}" -%> +<% gcp_kms_crypto_key_name_policy = "#{external_attribute('gcp_kms_crypto_key_name_policy', doc_generation)}" -%> +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('crypto_key_name') { should cmp <%= gcp_kms_crypto_key_name_policy -%> } + its('primary_state') { should eq "ENABLED" } + its('purpose') { should eq "ENCRYPT_DECRYPT" } + its('next_rotation_time') { should be > Time.now - 100000 } + its('create_time') { should be > Time.now - 365*60*60*24*10 } +end + +describe google_kms_crypto_key(project: <%= gcp_project_id -%>, location: <%= gcp_location -%>, key_ring_name: <%= gcp_kms_key_ring_policy_name -%>, name: "nonexistent") do + it { should_not exist } +end \ No newline at end of file diff --git a/templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_key_attributes.erb b/templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_key_attributes.erb new file mode 100644 index 000000000000..faa559c36528 --- /dev/null +++ b/templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_key_attributes.erb @@ -0,0 +1,5 @@ +gcp_project_id = attribute(:gcp_project_id, default: '<%= external_attribute('gcp_project_id') -%>', description: 'The GCP project identifier.') +gcp_location = attribute(:gcp_location, default: '<%= external_attribute('gcp_location') -%>', description: 'GCP location') +gcp_kms_key_ring_policy_name = attribute(:gcp_kms_key_ring_policy_name, default: '<%= external_attribute('gcp_kms_key_ring_policy_name') -%>', description: 'Key ring name') +gcp_kms_crypto_key_name_policy = attribute(:gcp_kms_crypto_key_name_policy, default: '<%= external_attribute('gcp_kms_crypto_key_name_policy') -%>', description: 'Key name') +gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources, default: '<%= external_attribute('gcp_enable_privileged_resources') -%>', description: 'If we are running tests with escalated permissions(required for this test)') \ No newline at end of file diff --git a/templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_keys.erb b/templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_keys.erb new file mode 100644 index 000000000000..97a25781bbaa --- /dev/null +++ b/templates/inspec/examples/google_kms_crypto_key/google_kms_crypto_keys.erb @@ -0,0 +1,8 @@ +<% gcp_project_id = "#{external_attribute('gcp_project_id', doc_generation)}" -%> +<% gcp_location = "#{external_attribute('gcp_location', doc_generation)}" -%> +<% gcp_kms_key_ring_policy_name = "#{external_attribute('gcp_kms_key_ring_policy_name', doc_generation)}" -%> +<% gcp_kms_crypto_key_name_policy = "#{external_attribute('gcp_kms_crypto_key_name_policy', doc_generation)}" -%> +describe google_kms_crypto_keys(project: <%= gcp_project_id -%>, location: <%= gcp_location -%>, key_ring_name: <%= gcp_kms_key_ring_policy_name -%>) do + its('count') { should be >= 1 } + its('crypto_key_names') { should include <%= gcp_kms_crypto_key_name_policy -%> } +end \ No newline at end of file diff --git a/templates/inspec/examples/google_kms_key_ring/google_kms_key_ring.erb b/templates/inspec/examples/google_kms_key_ring/google_kms_key_ring.erb new file mode 100644 index 000000000000..4648cbe70bfb --- /dev/null +++ b/templates/inspec/examples/google_kms_key_ring/google_kms_key_ring.erb @@ -0,0 +1,13 @@ +<% gcp_project_id = "#{external_attribute('gcp_project_id', doc_generation)}" -%> +<% gcp_location = "#{external_attribute('gcp_location', doc_generation)}" -%> +<% gcp_kms_key_ring_policy_name = "#{external_attribute('gcp_kms_key_ring_policy_name', doc_generation)}" -%> +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') { should be > Time.now - 365*60*60*24*10 } + its('key_ring_name'){ should eq <%= gcp_kms_key_ring_policy_name -%> } + its('key_ring_url'){ should match <%= gcp_kms_key_ring_policy_name -%> } +end + +describe google_kms_key_ring(project: <%= gcp_project_id -%>, location: <%= gcp_location -%>, name: "nonexistent") do + it { should_not exist } +end \ No newline at end of file diff --git a/templates/inspec/examples/google_kms_key_ring/google_kms_key_ring_attributes.erb b/templates/inspec/examples/google_kms_key_ring/google_kms_key_ring_attributes.erb new file mode 100644 index 000000000000..afa8f5370236 --- /dev/null +++ b/templates/inspec/examples/google_kms_key_ring/google_kms_key_ring_attributes.erb @@ -0,0 +1,4 @@ +gcp_project_id = attribute(:gcp_project_id, default: '<%= external_attribute('gcp_project_id') -%>', description: 'The GCP project identifier.') +gcp_location = attribute(:gcp_location, default: '<%= external_attribute('gcp_location') -%>', description: 'GCP location') +gcp_kms_key_ring_policy_name = attribute(:gcp_kms_key_ring_policy_name, default: '<%= external_attribute('gcp_kms_key_ring_policy_name') -%>', description: 'Key ring name') +gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources, default: '<%= external_attribute('gcp_enable_privileged_resources') -%>', description: 'If we are running tests with escalated permissions(required for this test)') \ No newline at end of file diff --git a/templates/inspec/examples/google_kms_key_ring/google_kms_key_rings.erb b/templates/inspec/examples/google_kms_key_ring/google_kms_key_rings.erb new file mode 100644 index 000000000000..7c904825d9fb --- /dev/null +++ b/templates/inspec/examples/google_kms_key_ring/google_kms_key_rings.erb @@ -0,0 +1,14 @@ +<% gcp_project_id = "#{external_attribute('gcp_project_id', doc_generation)}" -%> +<% gcp_location = "#{external_attribute('gcp_location', doc_generation)}" -%> +<% gcp_kms_key_ring_policy_name = "#{external_attribute('gcp_kms_key_ring_policy_name', doc_generation)}" -%> +describe google_kms_key_rings(project: <%= gcp_project_id -%>, location: <%= gcp_location -%>) do + its('key_ring_names'){ should include <%= gcp_kms_key_ring_policy_name -%> } +end + +describe.one do + google_kms_key_rings(project: <%= gcp_project_id -%>, location: <%= gcp_location -%>).key_ring_urls do |url| + describe url do + it { should match <%= gcp_kms_key_ring_policy_name -%> } + end + end +end \ No newline at end of file diff --git a/templates/inspec/iam_policy/iam_policy.erb b/templates/inspec/iam_policy/iam_policy.erb index f0f4bb16f707..8731aa312477 100644 --- a/templates/inspec/iam_policy/iam_policy.erb +++ b/templates/inspec/iam_policy/iam_policy.erb @@ -39,6 +39,14 @@ identifiers = extract_identifiers(individual_url) "<%= object.name -%> IamPolicy #{@params[:<%= identifiers.last.underscore -%>]}" end + def iam_binding_roles + @bindings.map(&:role) + end + + def count + @bindings.size + end + private def product_url diff --git a/templates/inspec/plural_resource.erb b/templates/inspec/plural_resource.erb index d726657a6816..3550aaa72fd3 100644 --- a/templates/inspec/plural_resource.erb +++ b/templates/inspec/plural_resource.erb @@ -59,6 +59,9 @@ link_query_items = object&.nested_query&.keys&.first || object.collection_url_ke name, value = transform(key, hash) hash_with_symbols[name] = value end +<% if object.plural_custom_logic -%> +<%= lines(indent(compile(object.plural_custom_logic), 8)) -%> +<% end -%> converted.push(hash_with_symbols) end end diff --git a/third_party/inspec/custom_functions/kms_crypto_key.erb b/third_party/inspec/custom_functions/kms_crypto_key.erb new file mode 100644 index 000000000000..56c53cb342b9 --- /dev/null +++ b/third_party/inspec/custom_functions/kms_crypto_key.erb @@ -0,0 +1,3 @@ +def primary_state + @fetched['primary']['state'] +end \ No newline at end of file diff --git a/third_party/inspec/custom_functions/kms_key_ring.erb b/third_party/inspec/custom_functions/kms_key_ring.erb new file mode 100644 index 000000000000..f4cacc848011 --- /dev/null +++ b/third_party/inspec/custom_functions/kms_key_ring.erb @@ -0,0 +1,3 @@ +def key_ring_name + name_from_self_link(@key_ring_url) +end \ No newline at end of file diff --git a/third_party/inspec/custom_functions/kms_key_ring_name.erb b/third_party/inspec/custom_functions/kms_key_ring_name.erb new file mode 100644 index 000000000000..4be5d260a101 --- /dev/null +++ b/third_party/inspec/custom_functions/kms_key_ring_name.erb @@ -0,0 +1 @@ +hash_with_symbols[:key_ring_name] = name_from_self_link(hash['name']) \ No newline at end of file