Module: GClouder::Resources::Project::IAMPolicyBinding
Defined Under Namespace
Modules: Binding, Local, Remote
Class Method Summary
collapse
check, #cli_args, cli_args, included, load, valid_resources
Methods included from GCloud
#gcloud, included, #verify
load, #project, project
Methods included from Helpers
#hash_to_args, included, #module_exists?, #to_arg, #to_deep_merge_hash, #valid_json?
Methods included from Logging
#add, #bad, #change, #debug, #error, #fatal, #good, included, #info, log, loggers, #remove, report, #resource_state, setup, #warn, #warning
Methods included from Shell
included, #shell
Class Method Details
.clean ⇒ Object
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 16
def self.clean
return if undefined.empty?
:clean
undefined.each do |region, roles|
info region, indent: 2, heading: true
roles.each do |role|
info role["name"], indent: 3, heading: true
role["members"].each do |member|
message = member
message += " (not defined locally)"
warning message, indent: 4
end
end
end
end
|
.ensure ⇒ Object
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 179
def self.ensure
return if Local.list.empty?
Local.list.each do |region, roles|
info region, indent: 2, heading: true
roles.each do |role|
info role["name"], indent: 3, heading: true
role["members"].each do |member|
if member.start_with?("sink:")
sink_name = member
member = sink(member)
if member.empty? && cli_args[:dry_run]
add "unknown - serviceAccount does not exist [#{sink_name}]", indent: 4
next
elsif member.empty?
fatal "unable to find sink serviceAccount (writer identity) - does sink exist for name: #{sink_name}"
end
end
if policy_member?(project_id, role["name"], member)
good member, indent: 4
next
end
if project_owner?
add member, indent: 4
Binding.ensure(project_id, member, role["name"])
next
end
add "#{member} [skipping] (insufficient permissions to create user)", indent: 4
end
end
end
end
|
.executioner ⇒ Object
230
231
232
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 230
def self.executioner
GClouder::Project::ID.id
end
|
234
235
236
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 234
def self.executioner_formatted
"user:#{executioner.strip}"
end
|
12
13
14
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 12
def self.(stage = :ensure)
info "[#{stage}] project / iam-policy-binding", indent: 1, title: true
end
|
.is_service_account?(member) ⇒ Boolean
38
39
40
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 38
def self.is_service_account?(member)
member.include? "gserviceaccount.com"
end
|
.policy_member?(project, role, member) ⇒ Boolean
219
220
221
222
223
224
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 219
def self.policy_member?(project, role, member)
bindings = gcloud("--format json projects get-iam-policy #{project} | jq '.bindings[] | select(.role == \"roles/#{role}\")'", force: true)
return false if bindings.empty?
fatal "could not get policy bindings for project: #{project}" unless bindings.key?("members")
bindings["members"].include?(member)
end
|
.project_id ⇒ Object
226
227
228
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 226
def self.project_id
project["project_id"]
end
|
.project_owner? ⇒ Boolean
238
239
240
241
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 238
def self.project_owner?
return false unless executioner
policy_member?(project_id, "owner", executioner_formatted)
end
|
.resource?(resources, resource) ⇒ Boolean
92
93
94
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 92
def self.resource?(resources, resource)
!resources.fetch_with_default("name", resource, {}).empty?
end
|
.resource_array_append(resources, resource_name, resource_key, obj) ⇒ Object
96
97
98
99
100
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 96
def self.resource_array_append(resources, resource_name, resource_key, obj)
resource = resources.fetch_with_default("name", resource_name, {})
resource[resource_key] ||= []
resource[resource_key] << obj
end
|
.sink(member) ⇒ Object
173
174
175
176
177
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 173
def self.sink(member)
gcloud("beta logging sinks describe #{member.gsub('sink:', '')} | jq -r .writerIdentity", force: true).chomp
rescue
fatal "failed to lookup writer identity for sink: #{member}"
end
|
.undefined ⇒ Object
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
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 42
def self.undefined
Remote.list.each_with_object({}) do |(region, remote_roles), collection|
remote_roles.each do |remote_role|
role_found = false
next unless remote_role.key?("members")
remote_role["members"].each do |remote_member|
next unless Local.list.key?("global")
Local.list["global"].each do |e|
next unless e["name"] == remote_role["name"]
role_found = true
next if e["members"].include?(remote_member)
next if unmanaged_service_account?(remote_member)
collection["global"] ||= []
if !resource?(collection["global"], remote_role["name"])
collection["global"] << { "name" => remote_role["name"], "members" => [] }
end
resource_array_append(collection["global"], remote_role["name"], "members", remote_member)
end
end
next if role_found
collection["global"] ||= []
collection["global"] << remote_role
end
end
end
|
.unmanaged_service_account?(member) ⇒ Boolean
34
35
36
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 34
def self.unmanaged_service_account?(member)
is_service_account?(member) && !member.include?(project["project_id"])
end
|
.validate ⇒ Object
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
164
165
166
167
168
169
170
171
|
# File 'lib/gclouder/resources/project/iam_policy_binding.rb', line 102
def self.validate
return if Local.list.empty?
:validate
failure = false
Local.list.each do |region, roles|
info region, indent: 2, heading: true
next if roles.empty?
roles.each do |role|
if !role.is_a?(Hash)
bad "role type is not a Hash: #{role}"
failure = true
next
end
if !role.key?("name")
bad "missing key: name"
failure = true
next
end
if !role.key?("members")
bad "missing key: members"
failure = true
next
end
info role["name"], indent: 3, heading: true
unless role["members"].is_a?(Array)
bad "value not an array for key: #{role}", indent: 4
fatal "failure due to invalid config"
end
next unless role.key?("members")
role["members"].each do |member|
if !member.is_a?(String)
bad "member isn't a String: #{member}", indent: 3
failure = true
next
end
info member, indent: 4, heading: true
good "member is a String", indent: 5
case member
when /^user:/
good "member is a 'user'", indent: 5
when /^group:/
good "member is a 'group'", indent: 5
when /^serviceAccount:/
good "member is a 'serviceAccount'", indent: 5
when /^sink:/
good "member is a 'sink'", indent: 5
else
bad "member is an unknown type", indent: 5
failure = true
end
end
end
end
fatal "config validation failure" if failure
end
|