Skip to content

Commit

Permalink
Merge pull request #18 from inspec/add-plural-resources
Browse files Browse the repository at this point in the history
Add plural resources
  • Loading branch information
davymcaleer authored Jun 14, 2018
2 parents 461df50 + 30e03bf commit 66b06a7
Show file tree
Hide file tree
Showing 22 changed files with 502 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ group :development do
end

group :inspec do
gem 'inspec', '~> 2.1', '>= 2.1.78'
gem 'inspec', '~> 2.2', '>= 2.2.10'
end
76 changes: 76 additions & 0 deletions docs/resources/google_compute_firewalls.md.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
title: About the google_compute_firewalls Resource
platform: gcp
---

# google\_compute\_firewalls

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

<br>

## Syntax

A `google_compute_firewalls` resource block collects GCP firewalls by project then tests that group.

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

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

google_compute_firewalls(project: 'chef-inspec-gcp').firewall_names.each do |firewall_name|
describe google_compute_firewall(project: 'chef-inspec-gcp', name: firewall_name) do
it { should exist }
its('kind') { should eq "compute#firewall" }
end
end

<br>

## Examples

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

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

describe google_compute_firewalls(project: 'chef-inspec-gcp') do
its('count') { should be <= 100}
end

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

describe google_compute_firewalls(project: 'chef-inspec-gcp') do
its('firewall_names') { should include "my-app-firewall-rule" }
end

### Test that a particular named rule does not exist

describe google_compute_firewalls(project: 'chef-inspec-gcp') do
its('firewall_names') { should_not include "default-allow-ssh" }
end

### Test there are no firewalls for the "INGRESS" direction

describe google_compute_firewalls(project: 'chef-inspec-gcp').where(firewall_direction: 'INGRESS') do
it { should_not exist }
end

<br>

## Filter Criteria

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

## Properties

* `firewall_ids` - an array of google_compute_firewall identifier integers
* `firewall_names` - an array of google_compute_firewall name strings
* `firewall_directions`- an array of google_compute_firewall directions containing strings e.g. "INGRESS" or "EGRESS"

<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.
8 changes: 7 additions & 1 deletion docs/resources/google_compute_instance.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,17 @@ The following examples show how to use this InSpec audit resource.
its('first_network_interface_type'){ should eq "one_to_one_nat" }
end

### Test that a particular compute instance label key is present

describe google_compute_instance(project: 'chef-inspec-gcp', zone: 'us-east1-b', name: 'inspec-test-vm') do
its('labels_keys') { should include 'my_favourite_label' }
end

<br>

## Properties

* `cpu_platform`, `creation_timestamp`, `deletion_protection`, `disks`, `id`, `kind`, `label_fingerprint`, `machine_type`, `metadata`, `name`, `network_interfaces`, `scheduling`, `start_restricted`, `status`, `tags`, `zone`
* `cpu_platform`, `creation_timestamp`, `deletion_protection`, `disks`, `id`, `kind`, `label_fingerprint`, `machine_type`, `metadata`, `name`, `network_interfaces`, `scheduling`, `start_restricted`, `status`, `tags`, `zone`, `labels_keys`, `labels_values`

<br>

Expand Down
9 changes: 5 additions & 4 deletions docs/resources/google_compute_instances.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ platform: gcp

# google\_compute\_instances

Use the `google_compute_instances` InSpec audit resource to test properties of all GCP compute instances for a project in a particular zone.
Use the `google_compute_instances` InSpec audit resource to test properties of all, or a filtered group of, GCP compute instances for a project in a particular zone.

<br>

Expand Down Expand Up @@ -38,7 +38,7 @@ The following examples show how to use this InSpec audit resource.
### Test that there are no more than a specified number of instances in the project and zone

describe google_compute_instances(project: 'chef-inspec-gcp', zone: 'europe-west2-a') do
its('entries.count') { should be <= 100}
its('count') { should be <= 100}
end

### Test the exact number of instances in the project and zone
Expand All @@ -57,11 +57,12 @@ The following examples show how to use this InSpec audit resource.

## Filter Criteria

This resource currently does not support any filter criteria; it will always fetch all instances in the zone.
This resource supports the following filter criteria: `instance_id` and `instance_name`. Either of these may be used with `where`, as a block or as a method.

## Properties

* `instance_id`, `instance_name`
* `instance_ids` - an array of google_compute_instance identifier integers
* `instance_names` - an array of google_compute_instance name strings

<br>

Expand Down
57 changes: 57 additions & 0 deletions docs/resources/google_compute_zone.md.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: About the google_compute_zone Resource
platform: gcp
---

# google\_compute\_zone

Use the `google_compute_zone` InSpec audit resource to test properties of a single GCP compute zone.

<br>

## Syntax

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

describe google_compute_zone(project: 'chef-inspec-gcp', zone: '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 zone exists

describe google_compute_zone(project: 'chef-inspec-gcp', zone: 'us-east1-b') do
it { should exist }
end

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

describe google_compute_zone(project: 'chef-inspec-gcp', zone: 'us-east1-b') do
its('status') { should eq 'UP' }
# or equivalently
it { should be_up }
end

### Test that a GCP compute zone has an expected CPU platform

describe google_compute_zone(project: 'chef-inspec-gcp', zone: 'us-east1-b') do
its('available_cpu_platforms') { should include "Intel Skylake" }
end

<br>

## Properties

* `available_cpu_platforms`, `creation_timestamp`, `description`, `id`, `kind`, `name`, `region`, `status`, `region_name`

<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_zones.md.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: About the google_compute_zones Resource
platform: gcp
---

# google\_compute\_zones

Use the `google_compute_zones` InSpec audit resource to test properties of all, or a filtered group of, GCP compute zones for a project in a particular zone.

<br>

## Syntax

A `google_compute_zones` resource block collects GCP zones by project then tests that group.

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

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

google_compute_zones(project: 'chef-inspec-gcp').zone_names.each do |zone_name|
describe google_compute_zone(project: 'chef-inspec-gcp', zone: zone_name) do
it { should exist }
its('kind') { should eq "compute#zone" }
its('status') { should eq 'UP' }
end
end

<br>

## Examples

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

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

describe google_compute_zones(project: 'chef-inspec-gcp') do
its('count') { should be <= 100}
end

### Test the exact number of zones in the project

describe google_compute_zones(project: 'chef-inspec-gcp') do
its('zone_ids.count') { should cmp 9 }
end

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

describe google_compute_zones(project: 'chef-inspec-gcp') do
its('zone_names') { should include "us-east1-b" }
end

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

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

<br>

## Filter Criteria

This resource supports the following filter criteria: `zone_id`; `zone_name` and `zone_status`. Anyy of these may be used with `where`, as a block or as a method.

## Properties

* `zone_ids` - an array of google_compute_zone identifier integers
* `zone_names` - an array of google_compute_zone name strings
* `zone_statuses`- an array of google_compute_zone statuses

<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.
2 changes: 1 addition & 1 deletion libraries/google_compute_firewall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class GoogleComputeFirewall < GcpResourceBase
desc 'Verifies settings for a compute firewall rule'

example "
describe google_compute_firewall(project: 'chef-inspec-gcp', location: 'us-west2', name: 'gcp-inspec-test') do
describe google_compute_firewall(project: 'chef-inspec-gcp', name: 'gcp-inspec-test') do
it { should exist }
its('name') { should eq 'inspec-test' }
its('status') { should eq 'in_use' }
Expand Down
50 changes: 50 additions & 0 deletions libraries/google_compute_firewalls.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

require 'gcp_backend'

module Inspec::Resources
class GoogleComputeFirewalls < GcpResourceBase
name 'google_compute_firewalls'
desc 'Verifies settings for GCP compute firewalls in bulk'

example "
describe google_compute_firewalls(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(:firewall_ids, field: :firewall_id)
filter_table_config.add(:firewall_names, field: :firewall_name)
filter_table_config.add(:firewall_directions, field: :firewall_direction)
filter_table_config.connect(self, :fetch_data)

def fetch_data
firewall_rows = []
next_page = nil
loop do
catch_gcp_errors do
@firewalls = @gcp.gcp_compute_client.list_firewalls(@project, page_token: next_page)
end
return [] if !@firewalls.items
@firewalls.items.map do |firewall|
firewall_rows+=[{ firewall_id: firewall.id,
firewall_name: firewall.name,
firewall_direction: firewall.direction }]
end
next_page = @firewalls.next_page_token
break unless next_page
end
@table = firewall_rows
end
end
end
12 changes: 12 additions & 0 deletions libraries/google_compute_instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@ def machine_size
machine_type.split('/').last
end

# helper for returning label keys to perform checks
def labels_keys
return [] if !defined?(labels)
labels.item.keys
end

# helper for returning label values to perform checks
def labels_values
return [] if !defined?(labels)
labels.item.values
end

def exists?
!@instance.nil?
end
Expand Down
23 changes: 12 additions & 11 deletions libraries/google_compute_instances.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,24 @@ def initialize(opts = {})

# FilterTable setup
filter_table_config = FilterTable.create
filter_table_config.add_accessor(:where)
filter_table_config.add_accessor(:entries)
filter_table_config.add(:exist?) { |filter_table| !filter_table.entries.empty? }
filter_table_config.add(:count) { |filter_table| filter_table.entries.count }
filter_table_config.add(:instance_ids, field: :instance_id)
filter_table_config.add(:instance_names, field: :instance_name)
filter_table_config.add(:colors, field: :color, type: :simple)
filter_table_config.connect(self, :fetch_data)

def fetch_data
instance_rows = []
catch_gcp_errors do
@instances = @gcp.gcp_compute_client.list_instances(@project, @zone)
end
@instances.items.map do |instance|
instance_rows+=[{ instance_id: instance.id,
instance_name: instance.name }]
next_page = nil
loop do
catch_gcp_errors do
@instances = @gcp.gcp_compute_client.list_instances(@project, @zone, page_token: next_page)
end
return [] if !@instances.items
@instances.items.map do |instance|
instance_rows+=[{ instance_id: instance.id,
instance_name: instance.name }]
end
next_page = @instances.next_page_token
break unless next_page
end
@table = instance_rows
end
Expand Down
Loading

0 comments on commit 66b06a7

Please sign in to comment.