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

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

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
1 change: 1 addition & 0 deletions products/resourcemanager/inspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides
exclude: false
method_name_separator: ':'
fetch_iam_policy_verb: :POST
iam_conditions_request_type: :REQUEST_BODY
Organization: !ruby/object:Overrides::Inspec::ResourceOverride
privileged: true
# Name should be organizations/123456
Expand Down
1 change: 1 addition & 0 deletions provider/inspec/common~copy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@
'libraries/google/iam/property/iam_policy_audit_configs.rb': 'templates/inspec/iam_policy/properties/iam_policy_audit_configs.rb'
'libraries/google/iam/property/iam_policy_audit_configs_audit_log_configs.rb': 'templates/inspec/iam_policy/properties/iam_policy_audit_configs_audit_log_configs.rb'
'libraries/google/iam/property/iam_policy_bindings.rb': 'templates/inspec/iam_policy/properties/iam_policy_bindings.rb'
'libraries/google/iam/property/iam_binding_condition.rb': 'templates/inspec/iam_policy/properties/iam_binding_condition.rb'
'Gemfile': 'provider/inspec/Gemfile'
21 changes: 20 additions & 1 deletion templates/inspec/iam_binding/iam_binding.erb
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,38 @@ class <%= object.name -%>IamBinding < 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, '<%= object.iam_policy.fetch_iam_policy_verb.capitalize -%>')
@fetched = @connection.fetch(product_url, resource_base_url, params, '<%= object.iam_policy.fetch_iam_policy_verb.capitalize -%>'<% if object.iam_policy.iam_conditions_request_type == :REQUEST_BODY -%>, {'options' => {'requestedPolicyVersion' => 3 }}.to_json <% end -%>)
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
25 changes: 25 additions & 0 deletions templates/inspec/iam_binding/iam_binding.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,38 @@ describe <%= iam_resource_name -%>(<%= identifiers_out -%>, role: "roles/editor"
end
```

<% if object.iam_policy.iam_conditions_request_type == :REQUEST_BODY -%>

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 <%= iam_resource_name -%>(<%= identifiers_out -%>, role: "roles/browser", condition: { title: "my title" }) do
it { should exist }
its('members.count'){ should cmp 1 }
its('members') { should include 'user:[email protected]' }
its('condition.title') {should cmp 'my title' }
its('condition.expression') { should cmp "request.time < timestamp('2020-10-01T00:00:00.000Z')" }
end
```
<% end -%>

## Properties
Properties that can be accessed from the `<%= iam_resource_name -%>` 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.

<% if object.iam_policy.iam_conditions_request_type == :REQUEST_BODY -%>
* `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.

<% end -%>
<% unless @api.apis_required.empty? -%>

## GCP Permissions
Expand Down
14 changes: 14 additions & 0 deletions templates/inspec/iam_policy/iam_policy.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ end
end
end
```
<% if object.iam_policy.iam_conditions_request_type == :REQUEST_BODY -%>

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

## Properties
Properties that can be accessed from the `<%= iam_resource_name -%>` resource:
Expand All @@ -37,6 +41,16 @@ Properties that can be accessed from the `<%= iam_resource_name -%>` resource:

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

<% if object.iam_policy.iam_conditions_request_type == :REQUEST_BODY -%>
* `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.

<% end -%>
* `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
40 changes: 40 additions & 0 deletions templates/inspec/iam_policy/properties/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 templates/inspec/iam_policy/properties/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