Skip to content

Commit

Permalink
Inspec org log sink
Browse files Browse the repository at this point in the history
Signed-off-by: Modular Magician <magic-modules@google.com>
  • Loading branch information
slevenick authored and Stuart Paterson committed Aug 27, 2019
1 parent 7e1960b commit 72c95fb
Show file tree
Hide file tree
Showing 8 changed files with 320 additions and 2 deletions.
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?
!@fetched.nil?
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
@@ -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

0 comments on commit 72c95fb

Please sign in to comment.