-
Notifications
You must be signed in to change notification settings - Fork 9
/
alicloud_ram_policy.rb
163 lines (139 loc) · 5.27 KB
/
alicloud_ram_policy.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
require 'alicloud_backend'
class AliCloudRamPolicy < AliCloudResourceBase
name 'alicloud_ram_policy'
desc 'Verifies settings for a RAM Policy.'
example <<-EXAMPLE
describe alicloud_ram_policy('policy-1') do
it { should exist }
its('default_version') { should be 'v1' }
it { should have_statement('Effect' => 'Allow', 'Resource' => '*', 'Action' => 'ecs:Describe*') }
its('statement_count') { should > 1 }
its{'attached_users') { should include 'user-1' }
it { should be_attached_to_role('acs:ram::12345:role/role-1') }
its('attachment_count') { should be > 1 }
end
EXAMPLE
attr_reader :policy_name, :default_version, :policy_document,
:attached_users, :attached_roles, :attached_groups,
:attached_user_count, :attached_role_count, :attached_group_count,
:attachment_count
def initialize(opts = {})
opts = { policy_name: opts } if opts.is_a?(String)
super(opts)
validate_parameters(required: %i(policy_name region), allow: %i(type))
@opts = opts
if opts[:type]
@resp = get_policy(opts)
else
opts[:type] = 'Custom'
@resp = get_policy(opts)
if @resp.nil?
opts[:type] = 'System'
@resp = get_policy(opts)
end
end
return if @resp.nil?
@policy = @resp['Policy']
@policy_name = opts[:policy_name]
@default_version = @resp['Policy']['DefaultVersion']
@policy_document = @resp['DefaultPolicyVersion']['PolicyDocument']
@attached_users = @attached_groups = @attached_roles = @attachment_count = 0
entities = get_attached_entities(opts, opts[:type])
return if entities.nil?
@attached_users = entities['Users']['User'].map { |x| x['UserName'] }
@attached_user_count = @attached_users.length
@attached_groups = entities['Groups']['Group'].map { |x| x['GroupName'] }
@attached_group_count = @attached_groups.length
@attached_roles = entities['Roles']['Role'].map { |x| x['Arn'] }
@attached_role_count = @attached_roles.length
@attachment_count = @attached_user_count + @attached_group_count + @attached_role_count
end
def get_policy(opts)
filters = { RegionId: opts[:region],
PolicyName: opts[:policy_name],
PolicyType: opts[:type] }
catch_alicloud_errors('EntityNotExist.Policy') do
resp = @alicloud.ram_client.request(
action: 'GetPolicy',
params: filters,
opts: {
method: 'POST',
},
)
return resp
end
end
def exists?
end
def has_statement?(criteria = {})
return false unless @policy_document
document = JSON.parse(URI.decode_www_form_component(@policy_document), { symbolize_names: true })
statements = document[:Statement].is_a?(Array) ? document[:Statement] : [document[:Statement]].compact
# downcase keys to eliminate formatting issue
# put values in an array for standard match checking
criteria = criteria.each_with_object({}) { |(k, v), h| h[k.downcase.to_sym] = v.is_a?(Array) ? v : [v] }
return false if criteria.empty? || statements.empty?
allowed_statement_elements = %i(Action Effect Sid Resource NotAction NotResource)
# downcase keys to eliminate formatting issue
unless criteria.keys.all? { |k| allowed_statement_elements.map(&:downcase).include?(k) }
raise ArgumentError,
"Valid statement elements are #{allowed_statement_elements}, provided elements are: #{criteria.keys}"
end
statements.each do |statement|
# This is to comply with the document that allowing keys in lowercase format.
statement = statement.transform_keys(&:downcase)
@statement_match = false
criteria_match = []
criteria.each do |k_c, v_c|
criteria_match << v_c.all? do |v|
statement_item_in_array = statement[k_c].is_a?(Array) ? statement[k_c] : [statement[k_c]].compact
statement_item_in_array.include?(v)
end
end
@statement_match = true if criteria_match.all?(true)
break if criteria_match.all?(true)
end
@statement_match
end
def get_attached_entities(_policy_name, policy_type = 'Custom')
catch_alicloud_errors('EntityNotExist.Policy') do
resp = @alicloud.ram_client.request(
action: 'ListEntitiesForPolicy',
params: {
RegionId: opts[:region],
PolicyName: opts[:policy_name],
PolicyType: policy_type,
},
opts: {
method: 'POST',
},
)
return resp
end
end
def statement_count
return false unless @policy_document
document = JSON.parse(URI.decode_www_form_component(@policy_document), { symbolize_names: true })
statements = document[:Statement].is_a?(Hash) ? [document[:Statement]] : document[:Statement]
statements.length
end
def attached_to_user?(username)
!@attached_users.nil? && @attached_users.include?(username)
end
def attached_to_group?(group_name)
!@attached_groups.nil? && @attached_groups.include?(group_name)
end
def attached_to_role?(role_arn)
!@attached_roles.nil? && @attached_roles.include?(role_arn)
end
def attached?
@attachment_count.positive?
end
def resource_id
"#{@opts[:policy_name]}_#{@opts[:region]}"
end
def to_s
"AliCloud RAM Policy #{@opts[:policy_name]}"
end
end