From f8cf81c22eea066625b57b8020bd1664c5af79a8 Mon Sep 17 00:00:00 2001 From: Sam Levenick Date: Tue, 15 Jan 2019 23:19:23 +0000 Subject: [PATCH] Inspec resource record sets Signed-off-by: Modular Magician --- .../google_dns_resource_record_set.md | 32 +++++++++ .../google_dns_resource_record_sets.md | 33 +++++++++ libraries/google_dns_resource_record_set.rb | 72 +++++++++++++++++++ libraries/google_dns_resource_record_sets.rb | 72 +++++++++++++++++++ test/integration/build/gcp-mm.tf | 29 ++++++++ .../configuration/mm-attributes.yml | 16 +++++ .../google_dns_resource_record_set.rb | 43 +++++++++++ .../google_dns_resource_record_sets.rb | 43 +++++++++++ 8 files changed, 340 insertions(+) create mode 100644 docs/resources/google_dns_resource_record_set.md create mode 100644 docs/resources/google_dns_resource_record_sets.md create mode 100644 libraries/google_dns_resource_record_set.rb create mode 100644 libraries/google_dns_resource_record_sets.rb create mode 100644 test/integration/verify/controls/google_dns_resource_record_set.rb create mode 100644 test/integration/verify/controls/google_dns_resource_record_sets.rb diff --git a/docs/resources/google_dns_resource_record_set.md b/docs/resources/google_dns_resource_record_set.md new file mode 100644 index 000000000..277f93de7 --- /dev/null +++ b/docs/resources/google_dns_resource_record_set.md @@ -0,0 +1,32 @@ +--- +title: About the ResourceRecordSet resource +platform: gcp +--- + + +## Syntax +A `google_dns_resource_record_set` is used to test a Google ResourceRecordSet resource + +## Examples +``` +describe google_dns_resource_record_set(project: 'chef-gcp-inspec', name: 'backend.my.domain.com.', type: 'A', managed_zone: 'inspec-gcp-managed-zone') do + it { should exist } + its('type') { should eq 'A' } + its('ttl') { should eq '300' } + its('target') { should include '8.8.8.8' } + its('target') { should include '8.8.4.4' } +end +``` + +## Properties +Properties that can be accessed from the `google_dns_resource_record_set` resource: + + * `name`: For example, www.example.com. + + * `type`: One of valid DNS resource types. + + * `ttl`: Number of seconds that this ResourceRecordSet can be cached by resolvers. + + * `target`: As defined in RFC 1035 (section 5) and RFC 1034 (section 3.6.1) + + * `managed_zone`: Identifies the managed zone addressed by this request. Can be the managed zone name or id. diff --git a/docs/resources/google_dns_resource_record_sets.md b/docs/resources/google_dns_resource_record_sets.md new file mode 100644 index 000000000..785835fdd --- /dev/null +++ b/docs/resources/google_dns_resource_record_sets.md @@ -0,0 +1,33 @@ +--- +title: About the ResourceRecordSet resource +platform: gcp +--- + + +## Syntax +A `google_dns_resource_record_sets` is used to test a Google ResourceRecordSet resource + +## Examples +``` +describe google_dns_resource_record_sets(project: 'chef-gcp-inspec', name: 'backend.my.domain.com.', managed_zone: 'inspec-gcp-managed-zone') do + its('count') { should eq 3 } + its('types') { should include 'A' } + its('ttls') { should include '300' } + its('targets.flatten') { should include '8.8.8.8' } + its('targets.flatten') { should include '8.8.4.4' } +end +``` + +## Properties +Properties that can be accessed from the `google_dns_resource_record_sets` resource: + +See [google_dns_resource_record_set.md](google_dns_resource_record_set.md) for more detailed information + * `names`: an array of `google_dns_resource_record_set` name + * `types`: an array of `google_dns_resource_record_set` type + * `ttls`: an array of `google_dns_resource_record_set` ttl + * `targets`: an array of `google_dns_resource_record_set` target + * `managed_zones`: an array of `google_dns_resource_record_set` managed_zone + +## Filter Criteria +This resource supports all of the above properties as filter criteria, which can be used +with `where` as a block or a method. diff --git a/libraries/google_dns_resource_record_set.rb b/libraries/google_dns_resource_record_set.rb new file mode 100644 index 000000000..a7266353d --- /dev/null +++ b/libraries/google_dns_resource_record_set.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: false + +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in README.md and +# CONTRIBUTING.md located at the root of this package. +# +# ---------------------------------------------------------------------------- +require 'gcp_backend' + +# A provider to manage Google Cloud DNS resources. +class ResourceRecordSet < GcpResourceBase + name 'google_dns_resource_record_set' + desc 'ResourceRecordSet' + supports platform: 'gcp' + + attr_reader :name + attr_reader :type + attr_reader :ttl + attr_reader :target + attr_reader :managed_zone + def base + 'https://www.googleapis.com/dns/v1/' + end + + def url + 'projects/{{project}}/managedZones/{{managed_zone}}/rrsets?name={{name}}&type={{type}}' + end + + def initialize(params) + super(params.merge({ use_http_transport: true })) + fetched = @connection.fetch(base, url, params) + @fetched = unwrap(fetched, params) + parse unless @fetched.nil? + end + + def identity + %w{name type} + end + + def collection_item + 'rrsets' + end + + def unwrap(fetched, params) + fetched[collection_item].find { |result| identity.all? { |id| result[id.to_sym] == params[id] } } + end + + def parse + @name = @fetched['name'] + @type = @fetched['type'] + @ttl = @fetched['ttl'] + @target = @fetched['rrdatas'] + @managed_zone = @fetched['managed_zone'] + end + + # Handles parsing RFC3339 time string + def parse_time_string(time_string) + time_string ? Time.parse(time_string) : nil + end + + def exists? + !@fetched.nil? + end +end diff --git a/libraries/google_dns_resource_record_sets.rb b/libraries/google_dns_resource_record_sets.rb new file mode 100644 index 000000000..3ab457ab8 --- /dev/null +++ b/libraries/google_dns_resource_record_sets.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: false + +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in README.md and +# CONTRIBUTING.md located at the root of this package. +# +# ---------------------------------------------------------------------------- +require 'gcp_backend' +class ResourceRecordSets < GcpResourceBase + name 'google_dns_resource_record_sets' + desc 'ResourceRecordSet plural resource' + supports platform: 'gcp' + + attr_reader :table + + filter_table_config = FilterTable.create + + filter_table_config.add(:names, field: :name) + filter_table_config.add(:types, field: :type) + filter_table_config.add(:ttls, field: :ttl) + filter_table_config.add(:targets, field: :target) + filter_table_config.add(:managed_zones, field: :managed_zone) + + filter_table_config.connect(self, :table) + + def base + 'https://www.googleapis.com/dns/v1/' + end + + def url + 'projects/{{project}}/managedZones/{{managed_zone}}/rrsets' + end + + def api_names + { + 'rrdatas' => 'target', + } + end + + def initialize(params = {}) + super(params.merge({ use_http_transport: true })) + @params = params + @table = fetch_wrapped_resource('rrsets') + end + + def fetch_wrapped_resource(wrap_path) + # fetch_resource returns an array of responses (to handle pagination) + result = @connection.fetch_all(base, url, @params) + return if result.nil? + + # Conversion of string -> object hash to symbol -> object hash that InSpec needs + converted = [] + result.each do |response| + next if response.nil? || !response.key?(wrap_path) + response[wrap_path].each do |hash| + hash_with_symbols = {} + hash.each_pair { |k, v| api_names.key?(k) ? hash_with_symbols[api_names[k].to_sym] = v : hash_with_symbols[k.to_sym] = v } + converted.push(hash_with_symbols) + end + end + + converted + end +end diff --git a/test/integration/build/gcp-mm.tf b/test/integration/build/gcp-mm.tf index 9b7853230..7e7d27ec4 100644 --- a/test/integration/build/gcp-mm.tf +++ b/test/integration/build/gcp-mm.tf @@ -10,6 +10,14 @@ variable "subscription" { type = "map" } +variable "managed_zone" { + type = "map" +} + +variable "record_set" { + type = "map" +} + resource "google_compute_ssl_policy" "custom-ssl-policy" { name = "${var.ssl_policy["name"]}" min_tls_version = "${var.ssl_policy["min_tls_version"]}" @@ -29,3 +37,24 @@ resource "google_pubsub_subscription" "default" { topic = "${google_pubsub_topic.topic.name}" ack_deadline_seconds = "${var.subscription["ack_deadline_seconds"]}" } + +resource "google_dns_managed_zone" "prod" { + name = "${var.managed_zone["name"]}" + dns_name = "${var.managed_zone["dns_name"]}" + description = "${var.managed_zone["description"]}" + + labels = { + key = "${var.managed_zone["label_value"]}" + } + project = "${var.gcp_project_id}" +} + +resource "google_dns_record_set" "a" { + name = "${var.record_set["name"]}" + managed_zone = "${google_dns_managed_zone.prod.name}" + type = "${var.record_set["type"]}" + ttl = "${var.record_set["ttl"]}" + + rrdatas = ["${var.record_set["rrdatas1"]}", "${var.record_set["rrdatas2"]}"] + project = "${var.gcp_project_id}" +} diff --git a/test/integration/configuration/mm-attributes.yml b/test/integration/configuration/mm-attributes.yml index 2a441f272..53c2ca1ce 100644 --- a/test/integration/configuration/mm-attributes.yml +++ b/test/integration/configuration/mm-attributes.yml @@ -4,8 +4,24 @@ ssl_policy: profile: 'CUSTOM' custom_feature: 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384' custom_feature2: 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384' + topic: name: 'inspec-gcp-topic' + subscription: name: 'inspec-gcp-subscription' ack_deadline_seconds: 20 + +managed_zone: + name: 'inspec-gcp-managed-zone' + dns_name: 'my.domain.com.' + description: 'A test DNS zone' + label_key: key + label_value: 'value' + +record_set: + name: 'backend.my.domain.com.' + type: 'A' + ttl: 300 + rrdatas1: '8.8.8.8' + rrdatas2: '8.8.4.4' diff --git a/test/integration/verify/controls/google_dns_resource_record_set.rb b/test/integration/verify/controls/google_dns_resource_record_set.rb new file mode 100644 index 000000000..4cbeb88e1 --- /dev/null +++ b/test/integration/verify/controls/google_dns_resource_record_set.rb @@ -0,0 +1,43 @@ +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in README.md and +# CONTRIBUTING.md located at the root of this package. +# +# ---------------------------------------------------------------------------- + +title 'Test GCP google_dns_resource_record_set resource.' + +gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.') +record_set = attribute('record_set', default: { + "name": "backend.my.domain.com.", + "type": "A", + "ttl": 300, + "rrdatas1": "8.8.8.8", + "rrdatas2": "8.8.4.4" +}) +managed_zone = attribute('managed_zone', default: { + "name": "inspec-gcp-managed-zone", + "dns_name": "my.domain.com.", + "description": "A test DNS zone", + "label_key": "key", + "label_value": "value" +}) +control 'google_dns_resource_record_set-1.0' do + impact 1.0 + title 'google_dns_resource_record_set resource test' + + describe google_dns_resource_record_set(project: gcp_project_id, name: record_set['name'], type: record_set['type'], managed_zone: managed_zone['name']) do + it { should exist } + its('type') { should eq record_set['type'] } + its('ttl') { should eq record_set['ttl'] } + its('target') { should include record_set['rrdatas1'] } + its('target') { should include record_set['rrdatas2'] } + end +end diff --git a/test/integration/verify/controls/google_dns_resource_record_sets.rb b/test/integration/verify/controls/google_dns_resource_record_sets.rb new file mode 100644 index 000000000..9c9cad0d8 --- /dev/null +++ b/test/integration/verify/controls/google_dns_resource_record_sets.rb @@ -0,0 +1,43 @@ +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in README.md and +# CONTRIBUTING.md located at the root of this package. +# +# ---------------------------------------------------------------------------- + +title 'Test GCP google_dns_resource_record_sets resource.' + +gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.') +record_set = attribute('record_set', default: { + "name": "backend.my.domain.com.", + "type": "A", + "ttl": 300, + "rrdatas1": "8.8.8.8", + "rrdatas2": "8.8.4.4" +}) +managed_zone = attribute('managed_zone', default: { + "name": "inspec-gcp-managed-zone", + "dns_name": "my.domain.com.", + "description": "A test DNS zone", + "label_key": "key", + "label_value": "value" +}) +control 'google_dns_resource_record_sets-1.0' do + impact 1.0 + title 'google_dns_resource_record_sets resource test' + + describe google_dns_resource_record_sets(project: gcp_project_id, name: record_set['name'], managed_zone: managed_zone['name']) do + its('count') { should eq 3 } + its('types') { should include record_set['type'] } + its('ttls') { should include record_set['ttl'] } + its('targets.flatten') { should include record_set['rrdatas1'] } + its('targets.flatten') { should include record_set['rrdatas2'] } + end +end