Skip to content

Commit

Permalink
Merge pull request #46 from inspec/add-regions
Browse files Browse the repository at this point in the history
Add google_compute_region(s) resources, tests etc. and updated README.
  • Loading branch information
russellseymour authored Aug 29, 2018
2 parents 8d105fd + 27f3fb8 commit b91ff45
Show file tree
Hide file tree
Showing 10 changed files with 316 additions and 0 deletions.
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

0 comments on commit b91ff45

Please sign in to comment.