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 organization log sink resource #173

Merged
merged 5 commits into from
Aug 27, 2019
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: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ gem 'google-api-client'
gem 'google-cloud'
gem 'googleauth'
gem 'inifile'
gem 'rubocop'
gem 'inspec-bin'
gem 'rubocop'

group :development do
gem 'github_changelog_generator'
Expand Down
1 change: 0 additions & 1 deletion docs/resources/google_compute_instance_group_manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ describe google_compute_instance_group_manager(project: 'chef-gcp-inspec', zone:
its('named_ports.count') { should cmp 1 }
its('named_ports.first.name') { should eq 'port' }
its('named_ports.first.port') { should eq '80' }
its('instance_template') { should match 'gcp-managed-group-name' }
end

describe google_compute_instance_group_manager(project: 'chef-gcp-inspec', zone: 'zone', name: 'nonexistent') do
Expand Down
40 changes: 40 additions & 0 deletions docs/resources/google_logging_organization_log_sink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: About the google_logging_organization_log_sink resource
platform: gcp
---

## Syntax
A `google_logging_organization_log_sink` is used to test a Google OrganizationLogSink resource

## Examples
```
describe google_logging_organization_log_sink(organization: '190694428152', name: 'inspec-gcp-org-sink') do
it { should exist }
its('filter') { should cmp 'resource.type = gce_instance' }
end

describe google_logging_organization_log_sink(organization: '190694428152', name: 'nonexistent') do
it { should_not exist }
end
```

## Properties
Properties that can be accessed from the `google_logging_organization_log_sink` resource:

* `organization`: Id of the organization that this sink belongs to.

* `name`: Name of the log sink.

* `filter`: An advanced logs filter. The only exported log entries are those that are in the resource owning the sink and that match the filter.

* `destination`: The export destination.

* `writer_identity`: An IAM identity—a service account or group—under which Logging writes the exported log entries to the sink's destination. This field is set by sinks.create and sinks.update based on the value of uniqueWriterIdentity in those methods.

* `include_children`: If the field is false, the default, only the logs owned by the sink's parent resource are available for export. If the field is true, then logs from all the projects, folders, and billing accounts contained in the sink's parent resource are also available for export. Whether a particular log entry from the children is exported depends on the sink's filter expression.



## GCP Permissions

Ensure the [Stackdriver Logging API](https://console.cloud.google.com/apis/library/logging.googleapis.com/) is enabled for the current project.
33 changes: 33 additions & 0 deletions docs/resources/google_logging_organization_log_sinks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: About the google_logging_organization_log_sinks resource
platform: gcp
---

## Syntax
A `google_logging_organization_log_sinks` is used to test a Google OrganizationLogSink resource

## Examples
```
describe google_logging_organization_log_sinks(organization: '190694428152') do
its('names') { should include 'inspec-gcp-org-sink' }
end
```

## Properties
Properties that can be accessed from the `google_logging_organization_log_sinks` resource:

See [google_logging_organization_log_sink.md](google_logging_organization_log_sink.md) for more detailed information
* `organizations`: an array of `google_logging_organization_log_sink` organization
* `names`: an array of `google_logging_organization_log_sink` name
* `filters`: an array of `google_logging_organization_log_sink` filter
* `destinations`: an array of `google_logging_organization_log_sink` destination
* `writer_identities`: an array of `google_logging_organization_log_sink` writer_identity
* `include_children`: an array of `google_logging_organization_log_sink` include_children

## 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.

## GCP Permissions

Ensure the [Stackdriver Logging API](https://console.cloud.google.com/apis/library/logging.googleapis.com/) is enabled for the current project.
70 changes: 70 additions & 0 deletions libraries/google_logging_organization_log_sink.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# 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 Stackdriver Logging resources.
class OrganizationLogSink < GcpResourceBase
name 'google_logging_organization_log_sink'
desc 'OrganizationLogSink'
supports platform: 'gcp'

attr_reader :params
attr_reader :organization
attr_reader :name
attr_reader :filter
attr_reader :destination
attr_reader :writer_identity
attr_reader :include_children

def initialize(params)
super(params.merge({ use_http_transport: true }))
@params = params
@fetched = @connection.fetch(product_url, resource_base_url, params)
parse unless @fetched.nil?
end

def parse
@organization = @fetched['organization']
@name = @fetched['name']
@filter = @fetched['filter']
@destination = @fetched['destination']
@writer_identity = @fetched['writerIdentity']
@include_children = @fetched['includeChildren']
end

# Handles parsing RFC3339 time string
def parse_time_string(time_string)
time_string ? Time.parse(time_string) : nil
end

def exists?
[email protected]?
end

def to_s
"OrganizationLogSink #{@params[:name]}"
end

private

def product_url
'https://logging.googleapis.com/v2/'
end

def resource_base_url
'organizations/{{organization}}/sinks/{{name}}'
end
end
94 changes: 94 additions & 0 deletions libraries/google_logging_organization_log_sinks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# 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 OrganizationLogSinks < GcpResourceBase
name 'google_logging_organization_log_sinks'
desc 'OrganizationLogSink plural resource'
supports platform: 'gcp'

attr_reader :table

filter_table_config = FilterTable.create

filter_table_config.add(:organizations, field: :organization)
filter_table_config.add(:names, field: :name)
filter_table_config.add(:filters, field: :filter)
filter_table_config.add(:destinations, field: :destination)
filter_table_config.add(:writer_identities, field: :writer_identity)
filter_table_config.add(:include_children, field: :include_children)

filter_table_config.connect(self, :table)

def initialize(params = {})
super(params.merge({ use_http_transport: true }))
@params = params
@table = fetch_wrapped_resource('sinks')
end

def fetch_wrapped_resource(wrap_path)
# fetch_resource returns an array of responses (to handle pagination)
result = @connection.fetch_all(product_url, resource_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
{
'organization' => ->(obj) { return :organization, obj['organization'] },
'name' => ->(obj) { return :name, obj['name'] },
'filter' => ->(obj) { return :filter, obj['filter'] },
'destination' => ->(obj) { return :destination, obj['destination'] },
'writerIdentity' => ->(obj) { return :writer_identity, obj['writerIdentity'] },
'includeChildren' => ->(obj) { return :include_children, obj['includeChildren'] },
}
end

# Handles parsing RFC3339 time string
def parse_time_string(time_string)
time_string ? Time.parse(time_string) : nil
end

private

def product_url
'https://logging.googleapis.com/v2/'
end

def resource_base_url
'organizations/{{organization}}/sinks'
end
end
18 changes: 17 additions & 1 deletion test/integration/build/gcp-mm.tf
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ variable "region_backend_service" {
type = "map"
}

variable "org_sink" {
type = "map"
}

resource "google_compute_ssl_policy" "custom-ssl-policy" {
name = "${var.ssl_policy["name"]}"
min_tls_version = "${var.ssl_policy["min_tls_version"]}"
Expand Down Expand Up @@ -511,7 +515,7 @@ resource "google_sourcerepo_repository" "gcp-inspec-sourcerepo-repository" {
resource "google_folder" "inspec-gcp-folder" {
count = "${var.gcp_organization_id == "none" ? 0 : var.gcp_enable_privileged_resources}"
display_name = "${var.folder["display_name"]}"
parent = "${var.gcp_organization_id}"
parent = "organizations/${var.gcp_organization_id}"
}

resource "google_storage_bucket_object" "archive" {
Expand Down Expand Up @@ -552,4 +556,16 @@ resource "google_container_node_pool" "inspec-gcp-regional-node-pool" {
region = "${var.gcp_location}"
cluster = "${google_container_cluster.gcp-inspec-regional-cluster.name}"
node_count = "${var.regional_node_pool["node_count"]}"
}

resource "google_logging_organization_sink" "my-sink" {
count = "${var.gcp_organization_id == "none" ? 0 : var.gcp_enable_privileged_resources}"
name = "${var.org_sink.name}"
org_id = "${var.gcp_organization_id}"

# Can export to pubsub, cloud storage, or bigquery
destination = "storage.googleapis.com/${google_storage_bucket.generic-storage-bucket.name}"

# Log all WARN or higher severity messages relating to instances
filter = "${var.org_sink.filter}"
}
6 changes: 5 additions & 1 deletion test/integration/configuration/mm-attributes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,8 @@ regional_node_pool:
name: inspec-gcp-regional-node-pool
cluster_name: inspec-gcp-regional-node-pool-cluster
node_count: 1
initial_node_count: 1
initial_node_count: 1

org_sink:
name: inspec-gcp-org-sink
filter: resource.type = gce_instance
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.')
gcp_zone = attribute(:gcp_zone, default: 'gcp_zone', description: 'The GCP project zone.')
gcp_lb_mig1_name = attribute(:gcp_lb_mig1_name, default: 'gcp_lb_mig1_name', description: 'Managed instance group name.')
instance_group_manager = attribute('instance_group_manager', default: {
"name": "inspec-gcp-igm",
"base_instance_name": "igm",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# ----------------------------------------------------------------------------
#
# *** 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_logging_organization_log_sink resource.'

org_sink = attribute('org_sink', default: {"name"=>"inspec-gcp-org-sink", "filter"=>"resource.type = gce_instance"})
gcp_organization_id = attribute(:gcp_organization_id, default: gcp_organization_id, description: 'The identifier of the organization that is the parent of this folder')
gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources, default:0, description:'Flag to enable privileged resources requiring elevated privileges in GCP.')
control 'google_logging_organization_log_sink-1.0' do
impact 1.0
title 'google_logging_organization_log_sink resource test'

only_if { gcp_enable_privileged_resources.to_i == 1 && gcp_organization_id != ''}
describe google_logging_organization_log_sink(organization: gcp_organization_id, name: org_sink['name']) do
it { should exist }
its('filter') { should cmp org_sink['filter'] }
end

describe google_logging_organization_log_sink(organization: gcp_organization_id, name: 'nonexistent') do
it { should_not exist }
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# ----------------------------------------------------------------------------
#
# *** 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_logging_organization_log_sinks resource.'

org_sink = attribute('org_sink', default: {"name"=>"inspec-gcp-org-sink", "filter"=>"resource.type = gce_instance"})
gcp_organization_id = attribute(:gcp_organization_id, default: gcp_organization_id, description: 'The identifier of the organization that is the parent of this folder')
gcp_enable_privileged_resources = attribute(:gcp_enable_privileged_resources, default:0, description:'Flag to enable privileged resources requiring elevated privileges in GCP.')
control 'google_logging_organization_log_sinks-1.0' do
impact 1.0
title 'google_logging_organization_log_sinks resource test'

only_if { gcp_enable_privileged_resources.to_i == 1 && gcp_organization_id != ''}
describe google_logging_organization_log_sinks(organization: gcp_organization_id) do
its('names') { should include org_sink['name'] }
end
end