Skip to content

Commit

Permalink
Add google_storage_bucket_object and google_storage_object_acl resour…
Browse files Browse the repository at this point in the history
…ces, update README and tf file.

Signed-off-by: Stuart Paterson <[email protected]>
  • Loading branch information
Stuart Paterson committed Aug 15, 2018
1 parent f8bd897 commit f401f09
Show file tree
Hide file tree
Showing 9 changed files with 306 additions and 17 deletions.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,20 @@ Since this is an InSpec resource pack, it only defines InSpec resources. It incl

```bash
$ inspec init profile my-profile
Create new profile at /Users/skpaterson/my-profile
* Create directory libraries
* Create file README.md
* Create directory controls
* Create file controls/example.rb
* Create file inspec.yml
* Create file libraries/.gitkeep
```

Now update the default `inspec.yml` file to point to the InSpec GCP resource pack:

```yaml
name: my-profile
title: My own Oneview profile
title: My GCP InSpec Profile
version: 0.1.0
inspec_version: '>= 2.2.10'
depends:
Expand Down Expand Up @@ -87,7 +96,14 @@ The following resources are available in the InSpec GCP Profile
- [google_projects](docs/resources/google_projects.md)
- [google_service_account](docs/resources/google_service_account.md)
- [google_storage_bucket](docs/resources/google_storage_bucket.md)
- [google_storage_bucket_acl](docs/resources/google_storage_bucket_acl.md)
- [google_storage_bucket_iam_binding](docs/resources/google_storage_bucket_iam_binding.md)
- [google_storage_bucket_iam_bindings](docs/resources/google_storage_bucket_iam_bindings.md)
- [google_storage_bucket_object](docs/resources/google_storage_bucket_object.md)
- [google_storage_buckets](docs/resources/google_storage_buckets.md)
- [google_storage_default_object_acl](docs/resources/google_storage_default_object_acl.md)
- [google_storage_object_acl](docs/resources/google_storage_object_acl.md)
## Examples
Expand Down
70 changes: 70 additions & 0 deletions docs/resources/google_storage_bucket_object.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: About the google_storage_bucket_object Resource
platform: gcp
---

# google\_storage\_bucket\_object

Use the `google_storage_bucket_object` InSpec audit resource to test properties of a single GCP storage bucket object.

<br>

## Syntax

A `google_storage_bucket_object` resource block declares the tests for a single GCP storage bucket object by bucket name and object name:

describe google_storage_bucket_object(bucket: 'bucket-buvsjjcndqz', object: 'bucket-object-pmxbiikq') do
it { should exist }
end

<br>

## Examples

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

### Test that a GCP compute zone exists

describe google_storage_bucket_object(bucket: 'bucket-buvsjjcndqz', object: 'bucket-object-pmxbiikq') do
it { should exist }
end

### Test that a GCP storage bucket object has non-zero size

describe google_storage_bucket_object(bucket: 'bucket-buvsjjcndqz', object: 'bucket-object-pmxbiikq') do
its('size') { should be > 0 }
end

### Test that a GCP storage bucket object has the expected content type

describe google_storage_bucket_object(bucket: 'bucket-buvsjjcndqz', object: 'bucket-object-pmxbiikq') do
its('content_type') { should eq "text/plain; charset=utf-8" }
end


### Test that a GCP storage bucket object was created within a certain time period

describe google_storage_bucket_object(bucket: 'bucket-buvsjjcndqz', object: 'bucket-object-pmxbiikq') do
its('time_created_date') { should be > Time.now - 365*60*60*24*10 }
end


### Test that a GCP storage bucket object was last updated within a certain time period

describe google_storage_bucket_object(bucket: 'bucket-buvsjjcndqz', object: 'bucket-object-pmxbiikq') do
its('updated_date') { should be > Time.now - 365*60*60*24*10 }
end

<br>

## Properties

* `bucket`, `content_type`, `crc32c`, `etag`, `generation`, `id`, `kind`, `md5_hash`, `media_link`, `metageneration`, `name`, `size`, `storage_class`, `time_created_date`, `time_storage_class_updated_date`, `updated_date`

<br>


## GCP Permissions

Ensure the [Google Cloud Storage API](https://console.cloud.google.com/apis/api/storage-component.googleapis.com/) is enabled.
4 changes: 2 additions & 2 deletions docs/resources/google_storage_default_object_acl.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ The following examples show how to use this InSpec audit resource.

### Test that a GCP storage bucket ACL exists

describe google_storage_bucket_acl(bucket: 'bucket-buvsjjcndqz', entity: '[email protected]') do
describe google_storage_default_object_acl(bucket: 'bucket-buvsjjcndqz', entity: '[email protected]') do
it { should exist }
end

### Test that a GCP storage default object ACL has the expected role (READER, WRITER or OWNER)

describe google_storage_bucket_acl(bucket: 'bucket-buvsjjcndqz', entity: '[email protected]') do
describe google_storage_default_object_acl(bucket: 'bucket-buvsjjcndqz', entity: '[email protected]') do
its('role') { should eq 'OWNER' }
end

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

# google\_storage\_object\_acl

Use the `google_storage_object_acl` InSpec audit resource to test properties of a single GCP storage object ACL. See the [Google documentation for this here](https://cloud.google.com/storage/docs/access-control/lists) covering the possible values for 'entity' argument below.

<br>

## Syntax

A `google_storage_object_acl` resource block declares the tests for a single GCP storage object ACL by bucket name, object name and entity.

describe google_storage_object_acl(bucket: 'bucket-buvsjjcndqz', object: 'bucket-object-pmxbiikq', entity: '[email protected]') do
it { should exist }
end

<br>

## Examples

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

### Test that a GCP storage bucket ACL exists

describe google_storage_object_acl(bucket: 'bucket-buvsjjcndqz', object: 'bucket-object-pmxbiikq', entity: '[email protected]') do
it { should exist }
end

### Test that a GCP storage object ACL has the expected role (READER, WRITER or OWNER)

describe google_storage_object_acl(bucket: 'bucket-buvsjjcndqz', object: 'bucket-object-pmxbiikq', entity: '[email protected]') do
its('role') { should eq 'OWNER' }
end

<br>

## Properties

* `bucket`, `email`, `entity`, `etag`, `generation`, `id`, `kind`, `object`, `role`

<br>


## GCP Permissions

Ensure the [Google Cloud Storage API](https://console.cloud.google.com/apis/api/storage-component.googleapis.com/) is enabled.
53 changes: 53 additions & 0 deletions libraries/google_storage_bucket_object.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

require 'gcp_backend'
require 'time'

module Inspec::Resources
class GoogleStorageBucketObject < GcpResourceBase
name 'google_storage_bucket_object'
desc 'Verifies settings for a storage bucket object'

example "
describe google_storage_bucket_object(bucket: 'bucket-buvsjjcndqz', object: 'bucket-object-pmxbiikq') do
it { should exist }
end
"
def initialize(opts = {})
# Call the parent class constructor
super(opts)
@bucket = opts[:bucket]
@object = opts[:object]
catch_gcp_errors do
@bucket_object = @gcp.gcp_storage_client.get_object(@bucket, @object)
@time_created = @bucket_object.time_created
@time_updated = @bucket_object.updated
@time_class_updated = @bucket_object.time_storage_class_updated
create_resource_methods(@bucket_object)
end
end

def updated_date
return false if !defined?(@time_updated)
Time.parse(@time_updated.to_s)
end

def time_storage_class_updated_date
return false if !defined?(@time_class_updated)
Time.parse(@time_class_updated.to_s)
end

def time_created_date
return false if !defined?(@time_created)
Time.parse(@time_created.to_s)
end

def exists?
!@bucket_object.nil?
end

def to_s
"Bucket object #{@bucket}/#{@object}"
end
end
end
36 changes: 36 additions & 0 deletions libraries/google_storage_object_acl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

require 'gcp_backend'

module Inspec::Resources
class GoogleStorageObjectAcl < GcpResourceBase
name 'google_storage_object_acl'
desc 'Verifies settings for a storage object ACL'

example "
describe google_storage_object_acl(bucket: 'bucket-buvsjjcndqz', object: 'bucket-object-pmxbiikq', entity: '[email protected]') do
it { should exist }
end
"

def initialize(opts = {})
# Call the parent class constructor
super(opts)
@bucket = opts[:bucket]
@object = opts[:object]
@entity = opts[:entity]
catch_gcp_errors do
@acl = @gcp.gcp_storage_client.get_object_access_control(@bucket, @object, @entity)
create_resource_methods(@acl)
end
end

def exists?
!@acl.nil?
end

def to_s
"Storage Object ACL #{@object}"
end
end
end
53 changes: 39 additions & 14 deletions test/integration/build/gcp.tf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ provider "google" {
version = "~> 1.16"
}

resource "google_service_account" "generic_service_account_object_viewer" {
count = "${var.gcp_enable_privileged_resources}"
project = "${var.gcp_project_id}"
account_id = "object-viewer"
display_name = "${var.gcp_service_account_display_name}"
}

resource "google_compute_instance" "generic_internal_vm_instance" {
project = "${var.gcp_project_id}"
name = "${var.gcp_int_vm_name}"
Expand Down Expand Up @@ -143,13 +150,6 @@ resource "google_compute_instance" "generic_windows_internal_vm_instance" {
}
}

resource "google_service_account" "generic_service_account_object_viewer" {
count = "${var.gcp_enable_privileged_resources}"
project = "${var.gcp_project_id}"
account_id = "object-viewer"
display_name = "${var.gcp_service_account_display_name}"
}

resource "google_project_iam_custom_role" "generic_project_iam_custom_role" {
count = "${var.gcp_enable_privileged_resources}"
project = "${var.gcp_project_id}"
Expand Down Expand Up @@ -618,13 +618,6 @@ resource "google_storage_bucket_object" "bucket-object" {
content = "Bucket Object ${var.gcp_storage_bucket_object_name} for bucket ${var.gcp_storage_bucket_object} in ${var.gcp_project_id} with ACL."
}

resource "google_storage_bucket_object" "bucket-object-no-acl" {
count = "${var.gcp_enable_privileged_resources}"
name = "${var.gcp_storage_bucket_object_name}-no-acl"
bucket = "${google_storage_bucket.bucket-with-object.name}"
content = "Bucket Object ${var.gcp_storage_bucket_object_name} for bucket ${var.gcp_storage_bucket_object} in ${var.gcp_project_id} with no ACL added."
}

#finally, add object ACL

resource "google_storage_object_acl" "bucket-object-acl" {
Expand All @@ -638,4 +631,36 @@ resource "google_storage_object_acl" "bucket-object-acl" {
]
}

# try the last scenario of adding an IAM policy to an object

# note at the time of writing, terraform isn't supporting the IAM policy applied to storage object case
# https://www.terraform.io/docs/providers/google/r/storage_bucket_object.html

# will revisit based on outcome of https://github.com/terraform-providers/terraform-provider-google/issues/1871

//resource "google_storage_bucket_object" "bucket-object-attach-policy" {
// count = "${var.gcp_enable_privileged_resources}"
// name = "${var.gcp_storage_bucket_object_name}-iam"
// bucket = "${google_storage_bucket.bucket-with-object.name}"
// content = "Bucket Object ${var.gcp_storage_bucket_object_name} for bucket ${var.gcp_storage_bucket_object} in ${var.gcp_project_id} with IAM policy."
//}
//
//data "google_iam_policy" "object-iam-policy" {
// count = "${var.gcp_enable_privileged_resources}"
// binding {
// role = "roles/storage.admin"
//
// members = [ "serviceAccount:${google_service_account.generic_service_account_object_viewer.email}" ]
// }
//}
//
//# would expect this to be something like below:
//resource "google_storage_object_iam_policy" "object-iam-policy-add" {
// count = "${var.gcp_enable_privileged_resources}"
// bucket = "${google_storage_bucket.bucket-with-object.name}"
// object = "${google_storage_bucket_object.bucket-object-attach-policy.name}"
// policy_data = "${data.google_iam_policy.object-iam-policy.policy_data}"
//}


# END storage bucket resources
21 changes: 21 additions & 0 deletions test/integration/verify/controls/google_storage_bucket_object.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
title 'Storage Bucket Object Properties'

gcp_storage_bucket_object = attribute(:gcp_storage_bucket_object, default: '', description: 'The GCP bucket with objects.')
gcp_storage_bucket_object_name = attribute(:gcp_storage_bucket_object_name, default: '', description: 'The GCP bucket object 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-storage-bucket-object-1.0' do

only_if { gcp_enable_privileged_resources.to_i == 1 }
impact 1.0
title 'Ensure that the Storage Bucket Object has been created correctly'

describe google_storage_bucket_object(bucket: gcp_storage_bucket_object, object: gcp_storage_bucket_object_name) do
it { should exist }
its('name') { should eq gcp_storage_bucket_object_name }
its('size') { should be > 0 }
its('content_type') { should eq "text/plain; charset=utf-8" }
its('time_created_date') { should be > Time.now - 365*60*60*24*10 }
its('updated_date') { should be > Time.now - 365*60*60*24*10 }
end
end
19 changes: 19 additions & 0 deletions test/integration/verify/controls/google_storage_object_acl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
title 'Test single GCP storage object ACL'

gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
gcp_storage_bucket_object = attribute(:gcp_storage_bucket_object, default: '', description: 'The GCP bucket with objects.')
gcp_storage_bucket_object_name = attribute(:gcp_storage_bucket_object_name, default: '', description: 'The GCP bucket object 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-storage-object-acl-1.0' do

only_if { gcp_enable_privileged_resources.to_i == 1 }
impact 1.0
title 'Ensure storage default object ACL has the correct properties.'

describe google_storage_object_acl(bucket: gcp_storage_bucket_object, object: gcp_storage_bucket_object_name, entity: "user-object-viewer@#{gcp_project_id}.iam.gserviceaccount.com") do
it { should exist }
its('email') { should include "object-viewer@#{gcp_project_id}.iam.gserviceaccount.com" }
its('role') { should eq "OWNER" }
end
end

0 comments on commit f401f09

Please sign in to comment.