Skip to content

Commit f97616c

Browse files
slevenickNathan Klish
authored and
Nathan Klish
committed
Support for IAM conditions in InSpec, currently only for project (GoogleCloudPlatform#3277)
1 parent 1622f8b commit f97616c

File tree

7 files changed

+105
-1
lines changed

7 files changed

+105
-1
lines changed

products/resourcemanager/inspec.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides
3333
exclude: false
3434
method_name_separator: ':'
3535
fetch_iam_policy_verb: :POST
36+
iam_conditions_request_type: :REQUEST_BODY
3637
Organization: !ruby/object:Overrides::Inspec::ResourceOverride
3738
privileged: true
3839
# Name should be organizations/123456

provider/inspec/common~copy.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@
1414
'libraries/google/iam/property/iam_policy_audit_configs.rb': 'templates/inspec/iam_policy/properties/iam_policy_audit_configs.rb'
1515
'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'
1616
'libraries/google/iam/property/iam_policy_bindings.rb': 'templates/inspec/iam_policy/properties/iam_policy_bindings.rb'
17+
'libraries/google/iam/property/iam_binding_condition.rb': 'templates/inspec/iam_policy/properties/iam_binding_condition.rb'
1718
'Gemfile': 'provider/inspec/Gemfile'

templates/inspec/iam_binding/iam_binding.erb

+20-1
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,38 @@ class <%= object.name -%>IamBinding < GcpResourceBase
1212

1313
attr_reader :params
1414

15+
attr_reader :condition
16+
1517
def initialize(params)
1618
super(params.merge({ use_http_transport: true }))
1719
raise "Expected 'role' to be defined for iam_binding resource" unless params.key?(:role)
1820
@params = params
19-
@fetched = @connection.fetch(product_url, resource_base_url, params, '<%= object.iam_policy.fetch_iam_policy_verb.capitalize -%>')
21+
@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 -%>)
2022
parse unless @fetched.nil?
2123
end
2224

2325
def parse
2426
@bindings = GoogleInSpec::Iam::Property::IamPolicyBindingsArray.parse(@fetched['bindings'], to_s)
2527
@bindings.each do |binding|
2628
next if binding.role != params[:role]
29+
if params[:condition]
30+
# Control defines a condition, match via this condition
31+
condition = params[:condition]
32+
if condition[:title] && condition[:title] != binding&.condition&.title
33+
next
34+
end
35+
if condition[:description] && condition[:description] != binding&.condition&.description
36+
next
37+
end
38+
if condition[:expression] && condition[:expression] != binding&.condition&.expression
39+
next
40+
end
41+
else
42+
# No condition defined in control, skip any binding with a condition
43+
next unless (binding.condition.title.nil? && binding.condition.description.nil? && binding.condition.expression.nil?)
44+
end
2745
@members_list = binding.members
46+
@condition = binding.condition
2847
@iam_binding_exists = true
2948
end
3049
end

templates/inspec/iam_binding/iam_binding.md.erb

+25
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,38 @@ describe <%= iam_resource_name -%>(<%= identifiers_out -%>, role: "roles/editor"
2020
end
2121
```
2222

23+
<% if object.iam_policy.iam_conditions_request_type == :REQUEST_BODY -%>
24+
25+
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.
26+
27+
```
28+
describe <%= iam_resource_name -%>(<%= identifiers_out -%>, role: "roles/browser", condition: { title: "my title" }) do
29+
it { should exist }
30+
its('members.count'){ should cmp 1 }
31+
its('members') { should include 'user:testuser@example.com' }
32+
its('condition.title') {should cmp 'my title' }
33+
its('condition.expression') { should cmp "request.time < timestamp('2020-10-01T00:00:00.000Z')" }
34+
end
35+
```
36+
<% end -%>
37+
2338
## Properties
2439
Properties that can be accessed from the `<%= iam_resource_name -%>` resource:
2540

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

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

45+
<% if object.iam_policy.iam_conditions_request_type == :REQUEST_BODY -%>
46+
* `condition`: Contains information about when this binding is to be applied.
47+
48+
* `expression`: Textual representation of an expression in Common Expression Language syntax.
49+
50+
* `title`: An optional title for the expression, i.e. a short string describing its purpose.
51+
52+
* `description`: An optional description of the expression. This is a longer text which describes the expression.
53+
54+
<% end -%>
3055
<% unless @api.apis_required.empty? -%>
3156

3257
## GCP Permissions

templates/inspec/iam_policy/iam_policy.md.erb

+14
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ end
2525
end
2626
end
2727
```
28+
<% if object.iam_policy.iam_conditions_request_type == :REQUEST_BODY -%>
29+
30+
This resource supports [IAM conditions](https://cloud.google.com/iam/docs/conditions-overview).
31+
<% end -%>
2832

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

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

44+
<% if object.iam_policy.iam_conditions_request_type == :REQUEST_BODY -%>
45+
* `condition`: Contains information about when this binding is to be applied.
46+
47+
* `expression`: Textual representation of an expression in Common Expression Language syntax.
48+
49+
* `title`: An optional title for the expression, i.e. a short string describing its purpose.
50+
51+
* `description`: An optional description of the expression. This is a longer text which describes the expression.
52+
53+
<% end -%>
4054
* `audit_configs`: Specifies cloud audit logging configuration for this policy.
4155

4256
* `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.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# frozen_string_literal: false
2+
3+
# Copyright 2017 Google Inc.
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
module GoogleInSpec
17+
module Iam
18+
module Property
19+
class IamBindingCondition
20+
attr_reader :title
21+
22+
attr_reader :description
23+
24+
attr_reader :expression
25+
26+
def initialize(args = nil, parent_identifier = nil)
27+
return if args.nil?
28+
@parent_identifier = parent_identifier
29+
@title = args['title']
30+
@description = args['description']
31+
@expression = args['expression']
32+
end
33+
34+
def to_s
35+
"#{@parent_identifier} IamBindingCondition"
36+
end
37+
end
38+
end
39+
end
40+
end

templates/inspec/iam_policy/properties/iam_policy_bindings.rb

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16+
require 'google/iam/property/iam_binding_condition'
1617
module GoogleInSpec
1718
module Iam
1819
module Property
@@ -21,11 +22,14 @@ class IamPolicyBindings
2122

2223
attr_reader :members
2324

25+
attr_reader :condition
26+
2427
def initialize(args = nil, parent_identifier = nil)
2528
return if args.nil?
2629
@parent_identifier = parent_identifier
2730
@role = args['role']
2831
@members = args['members']
32+
@condition = GoogleInSpec::Iam::Property::IamBindingCondition.new(args['condition'], to_s)
2933
end
3034

3135
def to_s

0 commit comments

Comments
 (0)