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 ability to test individual as well as multiple organisations #110

Merged
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
59 changes: 59 additions & 0 deletions docs/resources/google_organization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: About the google_organization Resource
platform: gcp
---

# google\_organization

Use the `google_organization` InSpec audit resource to test properties of a GCP organization.

<br>

## Syntax

Google organization have a name, display name (or domain) and lifecycle state. For more info, please see [here](https://cloud.google.com/resource-manager/docs/creating-managing-organization).

A `google_organization` resource block declares the tests for a single GCP organization identified by `display_name` or `name`:

describe google_organization(display_name: 'google.com') do
it { should exist }
its('name') { should eq 'organizations/1234' }
its('display_name') { should eq 'google.com' }
end

describe google_organization(name: 'organizations/1234') do
it { should exist }
its('name') { should eq 'google.com' }
its('lifecycle_state') { should eq 'ACTIVE' }
end

<br>

## Examples

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

### Test that a GCP organization has the expected name

describe google_organization(name: 'organizations/1234') do
its('name') { should eq 'organizations/1234' }
end

### Test that a GCP organization has the expected lifecycle state e.g. "ACTIVE"

describe google_organization(display_name: 'google.com') do
its('lifecycle_state') { should eq "ACTIVE" }
end

<br>

## Properties

* `name`, `display_name`, `lifecycle_state`

<br>


## GCP Permissions

Ensure the [Cloud Resource Manager API](https://console.cloud.google.com/apis/library/cloudresourcemanager.googleapis.com/) is enabled for the project.
85 changes: 85 additions & 0 deletions docs/resources/google_organizations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
title: About the google_organizations Resource
platform: gcp
---

# google\_organizations

Use the `google_organizations` InSpec audit resource to test properties of all, or a filtered group of, GCP
organizations.

<br>

## Syntax

A `google_organizations` resource block collects GCP organizations then tests that group.

describe google_organizations do
it { should exist }
end

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

google_organizations.names.each do |name|
describe google_organization(name: name) do
it { should exist }
its('lifecycle_state') { should eq "ACTIVE" }
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 organizations available

describe google_organizations do
its('count') { should be <= 100}
end

### Test that an expected organization name is available

describe google_organizations do
its('names') { should include "organization/1234" }
end

### Test that an expected organization display name is available

describe google_organizations do
its('display_names') { should include "google.com" }
end

### Test that all organizations are ACTIVE

describe google_organizations do
its('lifecycle_state'){ should eq 'ACTIVE' }
end

### Test that a particular subset of ACTIVE organizations with display name 'goog*' exist

google_organizations.where(display_name: /^goog/, lifecycle_state: 'ACTIVE').names.each do |name|
describe google_organization(name: name) do
it { should exist }
end
end

<br>

## Filter Criteria

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

## Properties

* `names` - an array of google_organization identifier strings
* `display_names` - an array of google_organization display name strings
* `lifecycle_state`- an array of google_organization lifecycle state strings

<br>


## GCP Permissions

Ensure the [Cloud Resource Manager API](https://console.cloud.google.com/apis/library/cloudresourcemanager.googleapis.com/) is enabled for the project.
40 changes: 40 additions & 0 deletions libraries/google_organization.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

require 'gcp_backend'

module Inspec::Resources
class GoogleOrganization < GcpResourceBase
name 'google_organization'
desc 'Verifies settings for an organization'

example "
describe google_organization(name: 'google.com') do
it { should exist }
its('name') { should eq 'organizations/1234' }
its('display_name') { should eq 'google.com' }
its('lifecycle_state') { should eq 'ACTIVE' }
end
"
def initialize(opts = {})
super(opts)
@display_name = opts[:name] || opts[:display_name]
catch_gcp_errors do
@organization = @gcp.gcp_project_client.get_organization(opts[:name])
create_resource_methods(@organization)
end
end

def label_value_by_key(label_key)
return [] if !defined?(labels) || labels.nil?
labels.item[label_key]
end

def exists?
[email protected]?
end

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

require 'gcp_backend'

module Inspec::Resources
class GoogleComputeOrganizations < GcpResourceBase
name 'google_organizations'
desc 'Verifies settings for GCP organizations in bulk'

example "
describe google_organizations do
it { should exist }
...
end
"

def initialize(opts = {})
super(opts)
end

filter_table_config = FilterTable.create
filter_table_config.add(:names, field: :name)
filter_table_config.add(:display_names, field: :display_name)
filter_table_config.add(:lifecycle_state, field: :lifecycle_state)
filter_table_config.connect(self, :fetch_data)

def fetch_data
organizations_rows = []
loop do
catch_gcp_errors do
@organizations = @gcp.gcp_project_client.search_organizations({})
end
return [] if !@organizations || [email protected]
@organizations.organizations.map do |organization|
organizations_rows += [{ name: organization.name,
display_name: organization.display_name,
lifecycle_state: organization.lifecycle_state }]
end
next_page = @organizations.next_page_token
break unless next_page
end
@table = organizations_rows
end
end
end
19 changes: 19 additions & 0 deletions test/integration/verify/controls/google_organization.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
title 'Test GCP Organization'

gcp_organization_id = attribute(:gcp_organization_id, default: '', description: 'The GCP organization identifier.')
gcp_organization_display_name = attribute(:gcp_organization_display_name, default: '', description: 'The GCP organization display name.')
gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources,default:0,description:'Flag to enable privileged resources requiring elevated privileges in GCP.')

control 'gcp-organization-1.0' do

only_if { gcp_enable_privileged_resources.to_i == 1 }
impact 1.0
title 'Ensure organization has the correct properties.'

describe google_organization(name: "organizations/#{gcp_organization_id}") do
it { should exist }
its('name') { should eq "organizations/#{gcp_organization_id}" }
its('display_name') { should eq gcp_organization_display_name }
its('lifecycle_state') { should include 'ACTIVE' }
end
end
19 changes: 19 additions & 0 deletions test/integration/verify/controls/google_organizations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
title 'Test GCP Organizations'

gcp_organization_id = attribute(:gcp_organization_id, default: '', description: 'The GCP organization identifier.')
gcp_organization_display_name = attribute(:gcp_organization_display_name, default: '', description: 'The GCP organization display name.')
gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources,default:0,description:'Flag to enable privileged resources requiring elevated privileges in GCP.')

control 'gcp-organizations-loop-1.0' do

only_if { gcp_enable_privileged_resources.to_i == 1 }
impact 1.0
title 'Ensure organizations have the correct properties in bulk.'

describe google_organizations do
it { should exist }
its('names'){ should include "organizations/#{gcp_organization_id}" }
its('display_names'){ should include gcp_organization_display_name }
its('lifecycle_state'){ should include 'ACTIVE' }
end
end