From 9ce89f7d0ce42cfd45e2f8843fad806a57b1749f Mon Sep 17 00:00:00 2001 From: Sam Levenick Date: Tue, 29 Jan 2019 22:38:16 +0000 Subject: [PATCH] Add support for target TCP proxy in InSpec Signed-off-by: Modular Magician --- .../google_compute_target_tcp_proxies.md | 31 +++++++ .../google_compute_target_tcp_proxy.md | 36 ++++++++ .../google_compute_target_tcp_proxies.rb | 92 +++++++++++++++++++ libraries/google_compute_target_tcp_proxy.rb | 61 ++++++++++++ test/integration/build/gcp-mm.tf | 20 ++++ .../configuration/mm-attributes.yml | 7 +- .../google_compute_target_tcp_proxies.rb | 31 +++++++ .../google_compute_target_tcp_proxy.rb | 36 ++++++++ 8 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 docs/resources/google_compute_target_tcp_proxies.md create mode 100644 docs/resources/google_compute_target_tcp_proxy.md create mode 100644 libraries/google_compute_target_tcp_proxies.rb create mode 100644 libraries/google_compute_target_tcp_proxy.rb create mode 100644 test/integration/verify/controls/google_compute_target_tcp_proxies.rb create mode 100644 test/integration/verify/controls/google_compute_target_tcp_proxy.rb diff --git a/docs/resources/google_compute_target_tcp_proxies.md b/docs/resources/google_compute_target_tcp_proxies.md new file mode 100644 index 000000000..7a240dece --- /dev/null +++ b/docs/resources/google_compute_target_tcp_proxies.md @@ -0,0 +1,31 @@ +--- +title: About the TargetTcpProxy resource +platform: gcp +--- + + +## Syntax +A `google_compute_target_tcp_proxies` is used to test a Google TargetTcpProxy resource + +## Examples +``` +describe google_compute_target_tcp_proxies(project: 'chef-gcp-inspec') do + its('names') { should include 'inspec-gcp-target-tcp-proxy' } + its('proxy_headers') { should include 'NONE' } +end +``` + +## Properties +Properties that can be accessed from the `google_compute_target_tcp_proxies` resource: + +See [google_compute_target_tcp_proxy.md](google_compute_target_tcp_proxy.md) for more detailed information + * `creation_timestamps`: an array of `google_compute_target_tcp_proxy` creation_timestamp + * `descriptions`: an array of `google_compute_target_tcp_proxy` description + * `ids`: an array of `google_compute_target_tcp_proxy` id + * `names`: an array of `google_compute_target_tcp_proxy` name + * `proxy_headers`: an array of `google_compute_target_tcp_proxy` proxy_header + * `services`: an array of `google_compute_target_tcp_proxy` service + +## 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/docs/resources/google_compute_target_tcp_proxy.md b/docs/resources/google_compute_target_tcp_proxy.md new file mode 100644 index 000000000..4a515d082 --- /dev/null +++ b/docs/resources/google_compute_target_tcp_proxy.md @@ -0,0 +1,36 @@ +--- +title: About the TargetTcpProxy resource +platform: gcp +--- + + +## Syntax +A `google_compute_target_tcp_proxy` is used to test a Google TargetTcpProxy resource + +## Examples +``` +describe google_compute_target_tcp_proxy(project: 'chef-gcp-inspec', name: 'inspec-gcp-target-tcp-proxy') do + it { should exist } + its('proxy_header') { should eq 'NONE' } + its('service') { should match /\/gcp-inspec-tcp-backend-service$/ } +end + +describe google_compute_target_tcp_proxy(project: 'chef-gcp-inspec', name: 'nonexistent') do + it { should_not exist } +end +``` + +## Properties +Properties that can be accessed from the `google_compute_target_tcp_proxy` resource: + + * `creation_timestamp`: Creation timestamp in RFC3339 text format. + + * `description`: An optional description of this resource. + + * `id`: The unique identifier for the resource. + + * `name`: Name of the resource. Provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. + + * `proxy_header`: Specifies the type of proxy header to append before sending data to the backend, either NONE or PROXY_V1. The default is NONE. + + * `service`: A reference to the BackendService resource. diff --git a/libraries/google_compute_target_tcp_proxies.rb b/libraries/google_compute_target_tcp_proxies.rb new file mode 100644 index 000000000..d3678bb91 --- /dev/null +++ b/libraries/google_compute_target_tcp_proxies.rb @@ -0,0 +1,92 @@ +# 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 TargetTcpProxys < GcpResourceBase + name 'google_compute_target_tcp_proxies' + desc 'TargetTcpProxy plural resource' + supports platform: 'gcp' + + attr_reader :table + + filter_table_config = FilterTable.create + + filter_table_config.add(:creation_timestamps, field: :creation_timestamp) + filter_table_config.add(:descriptions, field: :description) + filter_table_config.add(:ids, field: :id) + filter_table_config.add(:names, field: :name) + filter_table_config.add(:proxy_headers, field: :proxy_header) + filter_table_config.add(:services, field: :service) + + filter_table_config.connect(self, :table) + + def base + 'https://www.googleapis.com/compute/v1/' + end + + def url + 'projects/{{project}}/global/targetTcpProxies' + end + + def initialize(params = {}) + super(params.merge({ use_http_transport: true })) + @params = params + @table = fetch_wrapped_resource('items') + 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_key do |key| + name, value = transform(key, hash) + hash_with_symbols[name] = value + end + converted.push(hash_with_symbols) + end + end + + converted + end + + def transform(key, value) + return transformers[key].call(value) if transformers.key?(key) + + [key.to_sym, value] + end + + def transformers + { + 'creationTimestamp' => ->(obj) { return :creation_timestamp, parse_time_string(obj['creationTimestamp']) }, + 'description' => ->(obj) { return :description, obj['description'] }, + 'id' => ->(obj) { return :id, obj['id'] }, + 'name' => ->(obj) { return :name, obj['name'] }, + 'proxyHeader' => ->(obj) { return :proxy_header, obj['proxyHeader'] }, + 'service' => ->(obj) { return :service, obj['service'] }, + } + end + + # Handles parsing RFC3339 time string + def parse_time_string(time_string) + time_string ? Time.parse(time_string) : nil + end +end diff --git a/libraries/google_compute_target_tcp_proxy.rb b/libraries/google_compute_target_tcp_proxy.rb new file mode 100644 index 000000000..5927fe7a9 --- /dev/null +++ b/libraries/google_compute_target_tcp_proxy.rb @@ -0,0 +1,61 @@ +# 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 Compute Engine resources. +class TargetTcpProxy < GcpResourceBase + name 'google_compute_target_tcp_proxy' + desc 'TargetTcpProxy' + supports platform: 'gcp' + + attr_reader :creation_timestamp + attr_reader :description + attr_reader :id + attr_reader :name + attr_reader :proxy_header + attr_reader :service + def base + 'https://www.googleapis.com/compute/v1/' + end + + def url + 'projects/{{project}}/global/targetTcpProxies/{{name}}' + end + + def initialize(params) + super(params.merge({ use_http_transport: true })) + @fetched = @connection.fetch(base, url, params) + parse unless @fetched.nil? + end + + def parse + @creation_timestamp = parse_time_string(@fetched['creationTimestamp']) + @description = @fetched['description'] + @id = @fetched['id'] + @name = @fetched['name'] + @proxy_header = @fetched['proxyHeader'] + @service = @fetched['service'] + 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/test/integration/build/gcp-mm.tf b/test/integration/build/gcp-mm.tf index c214ce736..1977b3f0b 100644 --- a/test/integration/build/gcp-mm.tf +++ b/test/integration/build/gcp-mm.tf @@ -70,6 +70,10 @@ variable "global_forwarding_rule" { type = "map" } +variable "target_tcp_proxy" { + type = "map" +} + resource "google_compute_ssl_policy" "custom-ssl-policy" { name = "${var.ssl_policy["name"]}" min_tls_version = "${var.ssl_policy["min_tls_version"]}" @@ -288,4 +292,20 @@ resource "google_compute_global_forwarding_rule" "gcp-inspec-global-forwarding-r name = "${var.global_forwarding_rule["name"]}" target = "${google_compute_target_http_proxy.gcp-inspec-http-proxy.self_link}" port_range = "${var.global_forwarding_rule["port_range"]}" +} + +resource "google_compute_backend_service" "gcp-inspec-tcp-backend-service" { + project = "${var.gcp_project_id}" + name = "${var.target_tcp_proxy["tcp_backend_service_name"]}" + protocol = "TCP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.gcp-inspec-health-check.self_link}"] +} + +resource "google_compute_target_tcp_proxy" "gcp-inspec-target-tcp-proxy" { + project = "${var.gcp_project_id}" + name = "${var.target_tcp_proxy["name"]}" + proxy_header = "${var.target_tcp_proxy["proxy_header"]}" + backend_service = "${google_compute_backend_service.gcp-inspec-tcp-backend-service.self_link}" } \ No newline at end of file diff --git a/test/integration/configuration/mm-attributes.yml b/test/integration/configuration/mm-attributes.yml index 76bf03a26..db11d1e32 100644 --- a/test/integration/configuration/mm-attributes.yml +++ b/test/integration/configuration/mm-attributes.yml @@ -109,4 +109,9 @@ http_proxy: global_forwarding_rule: name: inspec-gcp-global-forwarding-rule - port_range: 80-80 \ No newline at end of file + port_range: 80-80 + +target_tcp_proxy: + name: inspec-gcp-target-tcp-proxy + proxy_header: NONE + tcp_backend_service_name: gcp-inspec-tcp-backend-service \ No newline at end of file diff --git a/test/integration/verify/controls/google_compute_target_tcp_proxies.rb b/test/integration/verify/controls/google_compute_target_tcp_proxies.rb new file mode 100644 index 000000000..12223ffcb --- /dev/null +++ b/test/integration/verify/controls/google_compute_target_tcp_proxies.rb @@ -0,0 +1,31 @@ +# ---------------------------------------------------------------------------- +# +# *** 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_compute_target_tcp_proxies resource.' + +gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.') +target_tcp_proxy = attribute('target_tcp_proxy', default: { + "name": "inspec-gcp-target-tcp-proxy", + "proxy_header": "NONE", + "tcp_backend_service_name": "gcp-inspec-tcp-backend-service" +}, description: 'Compute TCP proxy definition') +control 'google_compute_target_tcp_proxies-1.0' do + impact 1.0 + title 'google_compute_target_tcp_proxies resource test' + + describe google_compute_target_tcp_proxies(project: gcp_project_id) do + its('names') { should include target_tcp_proxy['name'] } + its('proxy_headers') { should include target_tcp_proxy['proxy_header'] } + end +end diff --git a/test/integration/verify/controls/google_compute_target_tcp_proxy.rb b/test/integration/verify/controls/google_compute_target_tcp_proxy.rb new file mode 100644 index 000000000..e40b6ecea --- /dev/null +++ b/test/integration/verify/controls/google_compute_target_tcp_proxy.rb @@ -0,0 +1,36 @@ +# ---------------------------------------------------------------------------- +# +# *** 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_compute_target_tcp_proxy resource.' + +gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.') +target_tcp_proxy = attribute('target_tcp_proxy', default: { + "name": "inspec-gcp-target-tcp-proxy", + "proxy_header": "NONE", + "tcp_backend_service_name": "gcp-inspec-tcp-backend-service" +}, description: 'Compute TCP proxy definition') +control 'google_compute_target_tcp_proxy-1.0' do + impact 1.0 + title 'google_compute_target_tcp_proxy resource test' + + describe google_compute_target_tcp_proxy(project: gcp_project_id, name: target_tcp_proxy['name']) do + it { should exist } + its('proxy_header') { should eq target_tcp_proxy['proxy_header'] } + its('service') { should match /\/gcp-inspec-tcp-backend-service$/ } + end + + describe google_compute_target_tcp_proxy(project: gcp_project_id, name: 'nonexistent') do + it { should_not exist } + end +end