@@ -30,6 +30,24 @@ import (
3030 "google.golang.org/api/cloudresourcemanager/v1"
3131)
3232
33+ type conditionKey struct {
34+ Description string
35+ Expression string
36+ Title string
37+ }
38+
39+ type iamBindingKey struct {
40+ Role string
41+ Condition conditionKey
42+ }
43+
44+ func conditionKeyFromCondition (condition * cloudresourcemanager.Expr ) conditionKey {
45+ if condition == nil {
46+ return conditionKey {}
47+ }
48+ return conditionKey {Description : condition .Description , Expression : condition .Expression , Title : condition .Title }
49+ }
50+
3351var IamBigqueryDatasetSchema = map [string ]* schema.Schema {
3452 "dataset_id" : {
3553 Type : schema .TypeString ,
@@ -93,8 +111,12 @@ func BigqueryDatasetIdParseFunc(d *schema.ResourceData, config *transport_tpg.Co
93111 return nil
94112}
95113
114+ func (u * BigqueryDatasetIamUpdater ) policyURL () string {
115+ return fmt .Sprintf ("%s%s?accessPolicyVersion=3" , u .Config .BigQueryBasePath , u .GetResourceId ())
116+ }
117+
96118func (u * BigqueryDatasetIamUpdater ) GetResourceIamPolicy () (* cloudresourcemanager.Policy , error ) {
97- url := fmt . Sprintf ( "%s%s" , u . Config . BigQueryBasePath , u . GetResourceId () )
119+ url := u . policyURL ( )
98120
99121 userAgent , err := tpgresource .GenerateUserAgentString (u .d , u .Config .UserAgent )
100122 if err != nil {
@@ -120,7 +142,7 @@ func (u *BigqueryDatasetIamUpdater) GetResourceIamPolicy() (*cloudresourcemanage
120142}
121143
122144func (u * BigqueryDatasetIamUpdater ) SetResourceIamPolicy (policy * cloudresourcemanager.Policy ) error {
123- url := fmt . Sprintf ( "%s%s" , u . Config . BigQueryBasePath , u . GetResourceId () )
145+ url := u . policyURL ( )
124146
125147 access , err := policyToAccess (policy )
126148 if err != nil {
@@ -154,7 +176,7 @@ func accessToPolicy(access interface{}) (*cloudresourcemanager.Policy, error) {
154176 if access == nil {
155177 return nil , nil
156178 }
157- roleToBinding := make (map [string ]* cloudresourcemanager.Binding )
179+ roleToBinding := make (map [iamBindingKey ]* cloudresourcemanager.Binding )
158180
159181 accessArr := access .([]interface {})
160182 for _ , v := range accessArr {
@@ -174,20 +196,32 @@ func accessToPolicy(access interface{}) (*cloudresourcemanager.Policy, error) {
174196 if err != nil {
175197 return nil , err
176198 }
177- // We have to combine bindings manually
178- binding , ok := roleToBinding [role ]
199+
200+ var condition * cloudresourcemanager.Expr
201+ if rawCondition , ok := memberRole ["condition" ]; ok {
202+ conditionMap := rawCondition .(map [string ]interface {})
203+ expr := conditionMap ["expression" ].(string )
204+ condition = & cloudresourcemanager.Expr {Expression : expr }
205+ if title , ok := conditionMap ["title" ].(string ); ok {
206+ condition .Title = title
207+ }
208+ if desc , ok := conditionMap ["description" ].(string ); ok {
209+ condition .Description = desc
210+ }
211+ }
212+
213+ key := iamBindingKey {Role : role , Condition : conditionKeyFromCondition (condition )}
214+ binding , ok := roleToBinding [key ]
179215 if ! ok {
180- binding = & cloudresourcemanager.Binding {Role : role , Members : []string {}}
216+ binding = & cloudresourcemanager.Binding {Role : role , Members : []string {}, Condition : condition }
181217 }
182218 binding .Members = append (binding .Members , member )
183-
184- roleToBinding [role ] = binding
219+ roleToBinding [key ] = binding
185220 }
186- bindings := make ([]* cloudresourcemanager.Binding , 0 )
221+ bindings := make ([]* cloudresourcemanager.Binding , 0 , len ( roleToBinding ) )
187222 for _ , v := range roleToBinding {
188223 bindings = append (bindings , v )
189224 }
190-
191225 return & cloudresourcemanager.Policy {Bindings : bindings }, nil
192226}
193227
@@ -197,9 +231,6 @@ func policyToAccess(policy *cloudresourcemanager.Policy) ([]map[string]interface
197231 return nil , errors .New ("Access policies not allowed on BigQuery Dataset IAM policies" )
198232 }
199233 for _ , binding := range policy .Bindings {
200- if binding .Condition != nil {
201- return nil , errors .New ("IAM conditions not allowed on BigQuery Dataset IAM" )
202- }
203234 if fullRole , ok := bigqueryAccessPrimitiveToRoleMap [binding .Role ]; ok {
204235 return nil , fmt .Errorf ("BigQuery Dataset legacy role %s is not allowed when using google_bigquery_dataset_iam resources. Please use the full form: %s" , binding .Role , fullRole )
205236 }
@@ -211,6 +242,9 @@ func policyToAccess(policy *cloudresourcemanager.Policy) ([]map[string]interface
211242 access := map [string ]interface {}{
212243 "role" : binding .Role ,
213244 }
245+ if binding .Condition != nil {
246+ access ["condition" ] = binding .Condition
247+ }
214248 memberType , member , err := iamMemberToAccess (member )
215249 if err != nil {
216250 return nil , err
@@ -279,11 +313,14 @@ func accessToIamMember(access map[string]interface{}) (string, error) {
279313 return "" , fmt .Errorf ("Failed to convert BigQuery Dataset access to IAM member. To use views with a dataset, please use dataset_access" )
280314 }
281315 if member , ok := access ["userByEmail" ]; ok {
282- // service accounts have "gservice" in their email. This is best guess due to lost information
283- if strings .Contains (member .(string ), "gserviceaccount" ) {
284- return fmt .Sprintf ("serviceAccount:%s" , member .(string )), nil
316+ ms := member .(string )
317+ if strings .HasPrefix (ms , "deleted:serviceAccount:" ) {
318+ return ms , nil
319+ }
320+ if strings .Contains (ms , "gserviceaccount" ) {
321+ return fmt .Sprintf ("serviceAccount:%s" , ms ), nil
285322 }
286- return fmt .Sprintf ("user:%s" , member .( string ) ), nil
323+ return fmt .Sprintf ("user:%s" , ms ), nil
287324 }
288325 return "" , fmt .Errorf ("Failed to identify IAM member from BigQuery Dataset access: %v" , access )
289326}
0 commit comments