4
4
"encoding/json"
5
5
"fmt"
6
6
"log"
7
+ "reflect"
7
8
"sort"
8
9
9
10
"github.com/hashicorp/errwrap"
@@ -88,8 +89,7 @@ func resourceGoogleProjectIamPolicyRead(d *schema.ResourceData, meta interface{}
88
89
return err
89
90
}
90
91
91
- // we only marshal the bindings, because only the bindings get set in the config
92
- policyBytes , err := json .Marshal (& cloudresourcemanager.Policy {Bindings : policy .Bindings })
92
+ policyBytes , err := json .Marshal (& cloudresourcemanager.Policy {Bindings : policy .Bindings , AuditConfigs : policy .AuditConfigs })
93
93
if err != nil {
94
94
return fmt .Errorf ("Error marshaling IAM policy: %v" , err )
95
95
}
@@ -157,7 +157,7 @@ func setProjectIamPolicy(policy *cloudresourcemanager.Policy, config *Config, pi
157
157
pbytes , _ := json .Marshal (policy )
158
158
log .Printf ("[DEBUG] Setting policy %#v for project: %s" , string (pbytes ), pid )
159
159
_ , err := config .clientResourceManager .Projects .SetIamPolicy (pid ,
160
- & cloudresourcemanager.SetIamPolicyRequest {Policy : policy }).Do ()
160
+ & cloudresourcemanager.SetIamPolicyRequest {Policy : policy , UpdateMask : "bindings,etag,auditConfigs" }).Do ()
161
161
162
162
if err != nil {
163
163
return errwrap .Wrapf (fmt .Sprintf ("Error applying IAM policy for project %q. Policy is %#v, error is {{err}}" , pid , policy ), err )
@@ -197,34 +197,67 @@ func jsonPolicyDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
197
197
log .Printf ("[ERROR] Could not unmarshal new policy %s: %v" , new , err )
198
198
return false
199
199
}
200
- oldPolicy .Bindings = mergeBindings (oldPolicy .Bindings )
201
- newPolicy .Bindings = mergeBindings (newPolicy .Bindings )
202
200
if newPolicy .Etag != oldPolicy .Etag {
203
201
return false
204
202
}
205
203
if newPolicy .Version != oldPolicy .Version {
206
204
return false
207
205
}
208
- if len ( newPolicy .Bindings ) != len ( oldPolicy .Bindings ) {
206
+ if ! compareBindings ( oldPolicy .Bindings , newPolicy .Bindings ) {
209
207
return false
210
208
}
211
- sort .Sort (sortableBindings (newPolicy .Bindings ))
212
- sort .Sort (sortableBindings (oldPolicy .Bindings ))
213
- for pos , newBinding := range newPolicy .Bindings {
214
- oldBinding := oldPolicy .Bindings [pos ]
215
- if oldBinding .Role != newBinding .Role {
216
- return false
217
- }
218
- if len (oldBinding .Members ) != len (newBinding .Members ) {
209
+ if ! compareAuditConfigs (oldPolicy .AuditConfigs , newPolicy .AuditConfigs ) {
210
+ return false
211
+ }
212
+ return true
213
+ }
214
+
215
+ func derefBindings (b []* cloudresourcemanager.Binding ) []cloudresourcemanager.Binding {
216
+ db := make ([]cloudresourcemanager.Binding , len (b ))
217
+
218
+ for i , v := range b {
219
+ db [i ] = * v
220
+ sort .Strings (db [i ].Members )
221
+ }
222
+ return db
223
+ }
224
+
225
+ func compareBindings (a , b []* cloudresourcemanager.Binding ) bool {
226
+ a = mergeBindings (a )
227
+ b = mergeBindings (b )
228
+ sort .Sort (sortableBindings (a ))
229
+ sort .Sort (sortableBindings (b ))
230
+ return reflect .DeepEqual (derefBindings (a ), derefBindings (b ))
231
+ }
232
+
233
+ func compareAuditConfigs (a , b []* cloudresourcemanager.AuditConfig ) bool {
234
+ a = mergeAuditConfigs (a )
235
+ b = mergeAuditConfigs (b )
236
+ sort .Sort (sortableAuditConfigs (a ))
237
+ sort .Sort (sortableAuditConfigs (b ))
238
+ if len (a ) != len (b ) {
239
+ return false
240
+ }
241
+ for i , v := range a {
242
+ if len (v .AuditLogConfigs ) != len (b [i ].AuditLogConfigs ) {
219
243
return false
220
244
}
221
- sort .Strings (oldBinding .Members )
222
- sort .Strings (newBinding .Members )
223
- for i , newMember := range newBinding .Members {
224
- oldMember := oldBinding .Members [i ]
225
- if newMember != oldMember {
245
+ sort .Sort (sortableAuditLogConfigs (v .AuditLogConfigs ))
246
+ sort .Sort (sortableAuditLogConfigs (b [i ].AuditLogConfigs ))
247
+ for x , logConfig := range v .AuditLogConfigs {
248
+ if b [i ].AuditLogConfigs [x ].LogType != logConfig .LogType {
249
+ return false
250
+ }
251
+ sort .Strings (logConfig .ExemptedMembers )
252
+ sort .Strings (b [i ].AuditLogConfigs [x ].ExemptedMembers )
253
+ if len (logConfig .ExemptedMembers ) != len (b [i ].AuditLogConfigs [x ].ExemptedMembers ) {
226
254
return false
227
255
}
256
+ for pos , exemptedMember := range logConfig .ExemptedMembers {
257
+ if b [i ].AuditLogConfigs [x ].ExemptedMembers [pos ] != exemptedMember {
258
+ return false
259
+ }
260
+ }
228
261
}
229
262
}
230
263
return true
@@ -242,6 +275,30 @@ func (b sortableBindings) Less(i, j int) bool {
242
275
return b [i ].Role < b [j ].Role
243
276
}
244
277
278
+ type sortableAuditConfigs []* cloudresourcemanager.AuditConfig
279
+
280
+ func (b sortableAuditConfigs ) Len () int {
281
+ return len (b )
282
+ }
283
+ func (b sortableAuditConfigs ) Swap (i , j int ) {
284
+ b [i ], b [j ] = b [j ], b [i ]
285
+ }
286
+ func (b sortableAuditConfigs ) Less (i , j int ) bool {
287
+ return b [i ].Service < b [j ].Service
288
+ }
289
+
290
+ type sortableAuditLogConfigs []* cloudresourcemanager.AuditLogConfig
291
+
292
+ func (b sortableAuditLogConfigs ) Len () int {
293
+ return len (b )
294
+ }
295
+ func (b sortableAuditLogConfigs ) Swap (i , j int ) {
296
+ b [i ], b [j ] = b [j ], b [i ]
297
+ }
298
+ func (b sortableAuditLogConfigs ) Less (i , j int ) bool {
299
+ return b [i ].LogType < b [j ].LogType
300
+ }
301
+
245
302
func getProjectIamPolicyMutexKey (pid string ) string {
246
303
return fmt .Sprintf ("iam-project-%s" , pid )
247
304
}
0 commit comments