Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add google_compute_region(s) resources, tests etc. and updated README. #46

Merged
merged 2 commits into from
Aug 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ The following resources are available in the InSpec GCP Profile
- [google_compute_networks](docs/resources/google_compute_networks.md)
- [google_compute_subnetwork](docs/resources/google_compute_subnetwork.md)
- [google_compute_subnetworks](docs/resources/google_compute_subnetworks.md)
- [google_compute_region](docs/resources/google_compute_region.md)
- [google_compute_regions](docs/resources/google_compute_regions.md)
- [google_compute_zone](docs/resources/google_compute_zone.md)
- [google_compute_zones](docs/resources/google_compute_zones.md)
- [google_container_cluster](docs/resources/google_container_cluster.md)
Expand Down
77 changes: 77 additions & 0 deletions docs/resources/google_compute_region.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: About the google_compute_region Resource
platform: gcp
---

# google\_compute\_region

Use the `google_compute_region` InSpec audit resource to test properties of a single GCP compute region.

<br>

## Syntax

A `google_compute_region` resource block declares the tests for a single GCP region by project and name.

describe google_compute_region(project: 'chef-inspec-gcp', region: 'us-east1-b') do
its('name') { should match 'us-east1-b' }
end

<br>

## Examples

The following examples show how to use this InSpec audit resource.

### Test that a GCP compute region exists

describe google_compute_region(project: 'chef-inspec-gcp', region: 'europe-west2') do
it { should exist }
end

### Test that a GCP compute region is in the expected state

describe google_compute_region(project: 'chef-inspec-gcp', region: 'europe-west2') do
its('status') { should eq 'UP' }
# or equivalently
it { should be_up }
end

### Test a GCP compute region identifier

describe google_compute_region(project: 'chef-inspec-gcp', region: "asia-east1") do
its('id') { should eq 1220 }
end

### Check that a region is associated with the expected zone fully qualified name

describe google_compute_region(project: 'chef-inspec-gcp', region: "asia-east1") do
its('zones') { should include "https://www.googleapis.com/compute/v1/projects/spaterson-project/zones/asia-east1-a" }
end

### Check that a region is associated with the expected zone short name

describe google_compute_region(project: 'chef-inspec-gcp', region: "asia-east1") do
its('zone_names') { should include "asia-east1-a" }
end

The `zone_names` property is also useful for subsequently looping over associated `google_compute_zone` resources. For example:

google_compute_region(project: 'chef-inspec-gcp', region: "asia-east1").zone_names.each do |zone_name|
describe google_compute_zone(project: 'chef-inspec-gcp', name: zone_name) do
it { should be_up }
end
end

<br>

## Properties

* `creation_timestamp`, `description`, `id`, `kind`, `name`, `quotas`, `status`, `zones`, `zone_names`

<br>


## GCP Permissions

Ensure the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com/) is enabled for the project where the resource is located.
77 changes: 77 additions & 0 deletions docs/resources/google_compute_regions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: About the google_compute_regions Resource
platform: gcp
---

# google\_compute\_regions

Use the `google_compute_regions` InSpec audit resource to test properties of all, or a filtered group of, GCP compute regions for a project.

<br>

## Syntax

A `google_compute_regions` resource block collects GCP regions by project then tests that group.

describe google_compute_regions(project: 'chef-inspec-gcp') do
it { should exist }
end

Use this InSpec resource to enumerate IDs then test in-depth using `google_compute_region`.

google_compute_regions(project: 'chef-inspec-gcp').region_names.each do |region_name|
describe google_compute_region(project: 'chef-inspec-gcp', region: region_name) do
it { should be_up }
end
end

<br>

## Examples

The following examples show how to use this InSpec audit resource.

### Test that there are more than a specified number of regions available for the project

describe google_compute_regions(project: 'chef-inspec-gcp') do
its('count') { should be >= 10}
end

### Test that an expected region is available for the project

describe google_compute_regions(project: 'chef-inspec-gcp') do
its('region_names') { should include 'europe-west2' }
end

### Test whether any regions are in status "DOWN"

describe google_compute_regions(project: 'chef-inspec-gcp') do
its('region_statuses') { should_not include "DOWN" }
end

### Test that a subset of all regions matching "europe*" are "UP"

describe google_compute_regions(project: gcp_project_id).where(region_name: /^europe/).region_names.each do |region_name|
describe google_compute_region(project: 'chef-inspec-gcp', region: region_name) do
it { should be_up }
end
end

<br>

## Filter Criteria

This resource supports the following filter criteria: `region_id`; `region_name` and `region_status`. Any of these may be used with `where`, as a block or as a method.

## Properties

* `region_ids` - an array of google_compute_region identifier integers
* `region_names` - an array of google_compute_region name strings
* `region_statuses`- an array of google_compute_region statuses

<br>


## GCP Permissions

Ensure the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com/) is enabled for the project.
46 changes: 46 additions & 0 deletions libraries/google_compute_region.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

require 'gcp_backend'

module Inspec::Resources
class GoogleComputeRegion < GcpResourceBase
name 'google_compute_region'
desc 'Verifies settings for a region'

example "
describe google_compute_region(project: 'chef-inspec-gcp', region: 'europe-west2') do
it { should exist }
end
"

def initialize(opts = {})
# Call the parent class constructor
super(opts)
@display_name = opts[:name]
catch_gcp_errors do
@region = @gcp.gcp_compute_client.get_region(opts[:project], opts[:name])
create_resource_methods(@region)
end
end

# helper for returning a list of zone short names rather than fully qualified URLs e.g.
# https://www.googleapis.com/compute/v1/projects/spaterson-project/zones/asia-east1-a
def zone_names
return false if !defined?(@region.zones)
@region.zones.map { |zone| zone.split('/').last }
end

def exists?
!@region.nil?
end

def up?
return false if !defined?(status)
status == 'UP'
end

def to_s
"Region #{@display_name}"
end
end
end
46 changes: 46 additions & 0 deletions libraries/google_compute_regions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

require 'gcp_backend'

module Inspec::Resources
class GoogleComputeRegions < GcpResourceBase
name 'google_compute_regions'
desc 'Verifies settings for GCP compute regions in bulk'

example "
describe google_compute_regions(project: 'chef-inspec-gcp') do
it { should exist }
...
end
"

def initialize(opts = {})
# Call the parent class constructor
super(opts)
@display_name = opts[:name]
@project = opts[:project]
end

# FilterTable setup
filter_table_config = FilterTable.create
filter_table_config.add(:region_ids, field: :region_id)
filter_table_config.add(:region_names, field: :region_name)
filter_table_config.add(:region_statuses, field: :region_status)
filter_table_config.connect(self, :fetch_data)

def fetch_data
region_rows = []
catch_gcp_errors do
# could paginate here but there are currently 17 regions and the limit on the below call is 500
@regions = @gcp.gcp_compute_client.list_regions(@project)
end
return [] if !@regions || !@regions.items
@regions.items.map do |region|
region_rows+=[{ region_id: region.id,
region_name: region.name,
region_status: region.status }]
end
@table = region_rows
end
end
end
1 change: 1 addition & 0 deletions test/integration/configuration/gcp_inspec_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def self.add_random_string(length=25)
:gcp_location => "europe-west2",
:gcp_zone => "europe-west2-a",
:gcp_zone_id => "2290",
:gcp_region_id => "1290",
:gcp_int_vm_name => "gcp-inspec-int-linux-vm",
:gcp_int_vm_size => "f1-micro",
:gcp_int_vm_image => "ubuntu-os-cloud/ubuntu-1604-lts",
Expand Down
16 changes: 16 additions & 0 deletions test/integration/verify/controls/google_compute_region.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
title 'Test single GCP Region'

gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
gcp_region = attribute(:gcp_location, default: '', description: 'The GCP region being used.')

control 'gcp-single-region-1.0' do

impact 1.0
title 'Ensure single region has the correct properties.'

describe google_compute_region(project: gcp_project_id, name: gcp_region) do
it { should exist }
it { should be_up }
its('zone_names') { should include "#{gcp_region}-a" }
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
title 'Loop over all zones in a GCP region'

gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
gcp_region = attribute(:gcp_location, default: '', description: 'The GCP region being used.')

control 'gcp-region-zones-loop-1.0' do

impact 1.0
title 'Ensure all zones in a region are available using google_compute_zone for detail.'

google_compute_region(project: gcp_project_id, name: gcp_region).zone_names.each do |zone_name|
describe google_compute_zone(project: gcp_project_id, name: zone_name) do
it { should be_up }
end
end
end
20 changes: 20 additions & 0 deletions test/integration/verify/controls/google_compute_regions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
title 'Regions Properties'

gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
gcp_region = attribute(:gcp_location, default: '', description: 'The GCP region being used.')
gcp_region_id = attribute(:gcp_region_id, default: '', description: 'A sample region identifier to test for.')

control 'gcp-regions-1.0' do

impact 1.0
title 'Ensure regions have the correct properties in bulk'

describe google_compute_regions(project: gcp_project_id) do
it { should exist }
its('count') { should be <= 100} # 17 at the time of writing
its('region_names') { should include gcp_region }
its('region_statuses') { should_not include "DOWN" }
its('region_ids') { should include gcp_region_id.to_i }
end

end
15 changes: 15 additions & 0 deletions test/integration/verify/controls/google_compute_regions_loop.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
title 'Loop over all GCP Regions'

gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')

control 'gcp-regions-loop-1.0' do

impact 1.0
title 'Ensure regions have the correct properties in bulk using google_compute_region for detail.'

google_compute_regions(project: gcp_project_id).region_names.each do |region_name|
describe google_compute_region(project: gcp_project_id, name: region_name) do
it { should be_up }
end
end
end