Skip to content
This repository was archived by the owner on Nov 14, 2024. It is now read-only.

Support for IAM conditions in InSpec, currently only for project #365

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
Support for IAM conditions in InSpec, currently only for project (#3277)
Signed-off-by: Modular Magician <magic-modules@google.com>
  • Loading branch information
modular-magician committed Mar 20, 2020
commit 30e05c20c161ab791574f16c1c3aded1624ad110
1 change: 1 addition & 0 deletions docs/resources/google_compute_subnetwork_iam_binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe google_compute_subnetwork_iam_binding(project: "project", region: "regi
end
```


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

Expand Down
1 change: 1 addition & 0 deletions docs/resources/google_kms_crypto_key_iam_binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe google_kms_crypto_key_iam_binding(project: "project", location: "locati
end
```


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

Expand Down
1 change: 1 addition & 0 deletions docs/resources/google_kms_key_ring_iam_binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe google_kms_key_ring_iam_binding(project: "project", location: "location
end
```


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

Expand Down
1 change: 1 addition & 0 deletions docs/resources/google_organization_iam_binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe google_organization_iam_binding(name: "name", role: "roles/editor") do
end
```


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

Expand Down
21 changes: 21 additions & 0 deletions docs/resources/google_project_iam_binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,34 @@ describe google_project_iam_binding(project: "project", role: "roles/editor") do
end
```


This resource supports [IAM conditions](https://cloud.google.com/iam/docs/conditions-overview). Specifying a `condition` in the constructor matches only bindings with that condition. `condition` has three possible fields, `title`, `expression` and `description`. If any of these fields are unspecified they will not be matched.

```
describe google_project_iam_binding(project: "project", role: "roles/browser", condition: { title: "my title" }) do
it { should exist }
its('members.count'){ should cmp 1 }
its('members') { should include 'user:testuser@example.com' }
its('condition.title') {should cmp 'my title' }
its('condition.expression') { should cmp "request.time < timestamp('2020-10-01T00:00:00.000Z')" }
end
```

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

* `role`: Role that is assigned to members. For example, roles/viewer, roles/editor, or roles/owner.

* `members`: Specifies the identities requesting access for a Cloud Platform resource.

* `condition`: Contains information about when this binding is to be applied.

* `expression`: Textual representation of an expression in Common Expression Language syntax.

* `title`: An optional title for the expression, i.e. a short string describing its purpose.

* `description`: An optional description of the expression. This is a longer text which describes the expression.


## GCP Permissions

Expand Down
10 changes: 10 additions & 0 deletions docs/resources/google_project_iam_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ google_project_iam_policy(project: "project").bindings.each do |binding|
end
```

This resource supports [IAM conditions](https://cloud.google.com/iam/docs/conditions-overview).

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

Expand All @@ -31,6 +33,14 @@ Properties that can be accessed from the `google_project_iam_policy` resource:

* `members`: Specifies the identities requesting access for a Cloud Platform resource.

* `condition`: Contains information about when this binding is to be applied.

* `expression`: Textual representation of an expression in Common Expression Language syntax.

* `title`: An optional title for the expression, i.e. a short string describing its purpose.

* `description`: An optional description of the expression. This is a longer text which describes the expression.

* `audit_configs`: Specifies cloud audit logging configuration for this policy.

* `service`: Specifies a service that will be enabled for audit logging. For example, `storage.googleapis.com`, `cloudsql.googleapis.com`. `allServices` is a special value that covers all services.
Expand Down
1 change: 1 addition & 0 deletions docs/resources/google_pubsub_subscription_iam_binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe google_pubsub_subscription_iam_binding(project: "project", name: "name"
end
```


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

Expand Down
1 change: 1 addition & 0 deletions docs/resources/google_pubsub_topic_iam_binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe google_pubsub_topic_iam_binding(project: "project", name: "name", role:
end
```


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

Expand Down
1 change: 1 addition & 0 deletions docs/resources/google_runtime_config_config_iam_binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe google_runtime_config_config_iam_binding(project: "project", name: "nam
end
```


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

Expand Down
1 change: 1 addition & 0 deletions docs/resources/google_spanner_instance_iam_binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe google_spanner_instance_iam_binding(project: "project", name: "name", r
end
```


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

Expand Down
1 change: 1 addition & 0 deletions docs/resources/google_storage_bucket_iam_binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe google_storage_bucket_iam_binding(bucket: "bucket", role: "roles/editor
end
```


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

Expand Down
40 changes: 40 additions & 0 deletions libraries/google/iam/property/iam_binding_condition.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: false

# Copyright 2017 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

module GoogleInSpec
module Iam
module Property
class IamBindingCondition
attr_reader :title

attr_reader :description

attr_reader :expression

def initialize(args = nil, parent_identifier = nil)
return if args.nil?
@parent_identifier = parent_identifier
@title = args['title']
@description = args['description']
@expression = args['expression']
end

def to_s
"#{@parent_identifier} IamBindingCondition"
end
end
end
end
end
4 changes: 4 additions & 0 deletions libraries/google/iam/property/iam_policy_bindings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

require 'google/iam/property/iam_binding_condition'
module GoogleInSpec
module Iam
module Property
Expand All @@ -21,11 +22,14 @@ class IamPolicyBindings

attr_reader :members

attr_reader :condition

def initialize(args = nil, parent_identifier = nil)
return if args.nil?
@parent_identifier = parent_identifier
@role = args['role']
@members = args['members']
@condition = GoogleInSpec::Iam::Property::IamBindingCondition.new(args['condition'], to_s)
end

def to_s
Expand Down
19 changes: 19 additions & 0 deletions libraries/google_compute_subnetwork_iam_binding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class SubnetworkIamBinding < GcpResourceBase

attr_reader :params

attr_reader :condition

def initialize(params)
super(params.merge({ use_http_transport: true }))
raise "Expected 'role' to be defined for iam_binding resource" unless params.key?(:role)
Expand All @@ -36,7 +38,24 @@ def parse
@bindings = GoogleInSpec::Iam::Property::IamPolicyBindingsArray.parse(@fetched['bindings'], to_s)
@bindings.each do |binding|
next if binding.role != params[:role]
if params[:condition]
# Control defines a condition, match via this condition
condition = params[:condition]
if condition[:title] && condition[:title] != binding&.condition&.title
next
end
if condition[:description] && condition[:description] != binding&.condition&.description
next
end
if condition[:expression] && condition[:expression] != binding&.condition&.expression
next
end
else
# No condition defined in control, skip any binding with a condition
next unless (binding.condition.title.nil? && binding.condition.description.nil? && binding.condition.expression.nil?)
end
@members_list = binding.members
@condition = binding.condition
@iam_binding_exists = true
end
end
Expand Down
19 changes: 19 additions & 0 deletions libraries/google_kms_crypto_key_iam_binding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class CryptoKeyIamBinding < GcpResourceBase

attr_reader :params

attr_reader :condition

def initialize(params)
super(params.merge({ use_http_transport: true }))
raise "Expected 'role' to be defined for iam_binding resource" unless params.key?(:role)
Expand All @@ -36,7 +38,24 @@ def parse
@bindings = GoogleInSpec::Iam::Property::IamPolicyBindingsArray.parse(@fetched['bindings'], to_s)
@bindings.each do |binding|
next if binding.role != params[:role]
if params[:condition]
# Control defines a condition, match via this condition
condition = params[:condition]
if condition[:title] && condition[:title] != binding&.condition&.title
next
end
if condition[:description] && condition[:description] != binding&.condition&.description
next
end
if condition[:expression] && condition[:expression] != binding&.condition&.expression
next
end
else
# No condition defined in control, skip any binding with a condition
next unless (binding.condition.title.nil? && binding.condition.description.nil? && binding.condition.expression.nil?)
end
@members_list = binding.members
@condition = binding.condition
@iam_binding_exists = true
end
end
Expand Down
19 changes: 19 additions & 0 deletions libraries/google_kms_key_ring_iam_binding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class KeyRingIamBinding < GcpResourceBase

attr_reader :params

attr_reader :condition

def initialize(params)
super(params.merge({ use_http_transport: true }))
raise "Expected 'role' to be defined for iam_binding resource" unless params.key?(:role)
Expand All @@ -36,7 +38,24 @@ def parse
@bindings = GoogleInSpec::Iam::Property::IamPolicyBindingsArray.parse(@fetched['bindings'], to_s)
@bindings.each do |binding|
next if binding.role != params[:role]
if params[:condition]
# Control defines a condition, match via this condition
condition = params[:condition]
if condition[:title] && condition[:title] != binding&.condition&.title
next
end
if condition[:description] && condition[:description] != binding&.condition&.description
next
end
if condition[:expression] && condition[:expression] != binding&.condition&.expression
next
end
else
# No condition defined in control, skip any binding with a condition
next unless (binding.condition.title.nil? && binding.condition.description.nil? && binding.condition.expression.nil?)
end
@members_list = binding.members
@condition = binding.condition
@iam_binding_exists = true
end
end
Expand Down
19 changes: 19 additions & 0 deletions libraries/google_organization_iam_binding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class OrganizationIamBinding < GcpResourceBase

attr_reader :params

attr_reader :condition

def initialize(params)
super(params.merge({ use_http_transport: true }))
raise "Expected 'role' to be defined for iam_binding resource" unless params.key?(:role)
Expand All @@ -36,7 +38,24 @@ def parse
@bindings = GoogleInSpec::Iam::Property::IamPolicyBindingsArray.parse(@fetched['bindings'], to_s)
@bindings.each do |binding|
next if binding.role != params[:role]
if params[:condition]
# Control defines a condition, match via this condition
condition = params[:condition]
if condition[:title] && condition[:title] != binding&.condition&.title
next
end
if condition[:description] && condition[:description] != binding&.condition&.description
next
end
if condition[:expression] && condition[:expression] != binding&.condition&.expression
next
end
else
# No condition defined in control, skip any binding with a condition
next unless (binding.condition.title.nil? && binding.condition.description.nil? && binding.condition.expression.nil?)
end
@members_list = binding.members
@condition = binding.condition
@iam_binding_exists = true
end
end
Expand Down
21 changes: 20 additions & 1 deletion libraries/google_project_iam_binding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,38 @@ class ProjectIamBinding < GcpResourceBase

attr_reader :params

attr_reader :condition

def initialize(params)
super(params.merge({ use_http_transport: true }))
raise "Expected 'role' to be defined for iam_binding resource" unless params.key?(:role)
@params = params
@fetched = @connection.fetch(product_url, resource_base_url, params, 'Post')
@fetched = @connection.fetch(product_url, resource_base_url, params, 'Post', {'options' => {'requestedPolicyVersion' => 3 }}.to_json )
parse unless @fetched.nil?
end

def parse
@bindings = GoogleInSpec::Iam::Property::IamPolicyBindingsArray.parse(@fetched['bindings'], to_s)
@bindings.each do |binding|
next if binding.role != params[:role]
if params[:condition]
# Control defines a condition, match via this condition
condition = params[:condition]
if condition[:title] && condition[:title] != binding&.condition&.title
next
end
if condition[:description] && condition[:description] != binding&.condition&.description
next
end
if condition[:expression] && condition[:expression] != binding&.condition&.expression
next
end
else
# No condition defined in control, skip any binding with a condition
next unless (binding.condition.title.nil? && binding.condition.description.nil? && binding.condition.expression.nil?)
end
@members_list = binding.members
@condition = binding.condition
@iam_binding_exists = true
end
end
Expand Down
Loading