@@ -14,6 +14,24 @@ import (
1414 "google.golang.org/api/cloudresourcemanager/v1"
1515)
1616
17+ type conditionKey struct {
18+ Description string
19+ Expression string
20+ Title string
21+ }
22+
23+ type iamBindingKey struct {
24+ Role string
25+ Condition conditionKey
26+ }
27+
28+ func conditionKeyFromCondition (condition * cloudresourcemanager.Expr ) conditionKey {
29+ if condition == nil {
30+ return conditionKey {}
31+ }
32+ return conditionKey {Description : condition .Description , Expression : condition .Expression , Title : condition .Title }
33+ }
34+
1735var IamBigqueryDatasetSchema = map [string ]* schema.Schema {
1836 "dataset_id" : {
1937 Type : schema .TypeString ,
@@ -77,8 +95,12 @@ func BigqueryDatasetIdParseFunc(d *schema.ResourceData, config *transport_tpg.Co
7795 return nil
7896}
7997
98+ func (u * BigqueryDatasetIamUpdater ) policyURL () string {
99+ return fmt .Sprintf ("%s%s?accessPolicyVersion=3" , u .Config .BigQueryBasePath , u .GetResourceId ())
100+ }
101+
80102func (u * BigqueryDatasetIamUpdater ) GetResourceIamPolicy () (* cloudresourcemanager.Policy , error ) {
81- url := fmt . Sprintf ( "%s%s" , u . Config . BigQueryBasePath , u . GetResourceId () )
103+ url := u . policyURL ( )
82104
83105 userAgent , err := tpgresource .GenerateUserAgentString (u .d , u .Config .UserAgent )
84106 if err != nil {
@@ -104,7 +126,7 @@ func (u *BigqueryDatasetIamUpdater) GetResourceIamPolicy() (*cloudresourcemanage
104126}
105127
106128func (u * BigqueryDatasetIamUpdater ) SetResourceIamPolicy (policy * cloudresourcemanager.Policy ) error {
107- url := fmt . Sprintf ( "%s%s" , u . Config . BigQueryBasePath , u . GetResourceId () )
129+ url := u . policyURL ( )
108130
109131 access , err := policyToAccess (policy )
110132 if err != nil {
@@ -138,7 +160,7 @@ func accessToPolicy(access interface{}) (*cloudresourcemanager.Policy, error) {
138160 if access == nil {
139161 return nil , nil
140162 }
141- roleToBinding := make (map [string ]* cloudresourcemanager.Binding )
163+ roleToBinding := make (map [iamBindingKey ]* cloudresourcemanager.Binding )
142164
143165 accessArr := access .([]interface {})
144166 for _ , v := range accessArr {
@@ -158,20 +180,32 @@ func accessToPolicy(access interface{}) (*cloudresourcemanager.Policy, error) {
158180 if err != nil {
159181 return nil , err
160182 }
161- // We have to combine bindings manually
162- binding , ok := roleToBinding [role ]
183+
184+ var condition * cloudresourcemanager.Expr
185+ if rawCondition , ok := memberRole ["condition" ]; ok {
186+ conditionMap := rawCondition .(map [string ]interface {})
187+ expr := conditionMap ["expression" ].(string )
188+ condition = & cloudresourcemanager.Expr {Expression : expr }
189+ if title , ok := conditionMap ["title" ].(string ); ok {
190+ condition .Title = title
191+ }
192+ if desc , ok := conditionMap ["description" ].(string ); ok {
193+ condition .Description = desc
194+ }
195+ }
196+
197+ key := iamBindingKey {Role : role , Condition : conditionKeyFromCondition (condition )}
198+ binding , ok := roleToBinding [key ]
163199 if ! ok {
164- binding = & cloudresourcemanager.Binding {Role : role , Members : []string {}}
200+ binding = & cloudresourcemanager.Binding {Role : role , Members : []string {}, Condition : condition }
165201 }
166202 binding .Members = append (binding .Members , member )
167-
168- roleToBinding [role ] = binding
203+ roleToBinding [key ] = binding
169204 }
170- bindings := make ([]* cloudresourcemanager.Binding , 0 )
205+ bindings := make ([]* cloudresourcemanager.Binding , 0 , len ( roleToBinding ) )
171206 for _ , v := range roleToBinding {
172207 bindings = append (bindings , v )
173208 }
174-
175209 return & cloudresourcemanager.Policy {Bindings : bindings }, nil
176210}
177211
@@ -181,9 +215,6 @@ func policyToAccess(policy *cloudresourcemanager.Policy) ([]map[string]interface
181215 return nil , errors .New ("Access policies not allowed on BigQuery Dataset IAM policies" )
182216 }
183217 for _ , binding := range policy .Bindings {
184- if binding .Condition != nil {
185- return nil , errors .New ("IAM conditions not allowed on BigQuery Dataset IAM" )
186- }
187218 if fullRole , ok := bigqueryAccessPrimitiveToRoleMap [binding .Role ]; ok {
188219 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 )
189220 }
@@ -195,6 +226,9 @@ func policyToAccess(policy *cloudresourcemanager.Policy) ([]map[string]interface
195226 access := map [string ]interface {}{
196227 "role" : binding .Role ,
197228 }
229+ if binding .Condition != nil {
230+ access ["condition" ] = binding .Condition
231+ }
198232 memberType , member , err := iamMemberToAccess (member )
199233 if err != nil {
200234 return nil , err
@@ -263,11 +297,14 @@ func accessToIamMember(access map[string]interface{}) (string, error) {
263297 return "" , fmt .Errorf ("Failed to convert BigQuery Dataset access to IAM member. To use views with a dataset, please use dataset_access" )
264298 }
265299 if member , ok := access ["userByEmail" ]; ok {
266- // service accounts have "gservice" in their email. This is best guess due to lost information
267- if strings .Contains (member .(string ), "gserviceaccount" ) {
268- return fmt .Sprintf ("serviceAccount:%s" , member .(string )), nil
300+ ms := member .(string )
301+ if strings .HasPrefix (ms , "deleted:serviceAccount:" ) {
302+ return ms , nil
303+ }
304+ if strings .Contains (ms , "gserviceaccount" ) {
305+ return fmt .Sprintf ("serviceAccount:%s" , ms ), nil
269306 }
270- return fmt .Sprintf ("user:%s" , member .( string ) ), nil
307+ return fmt .Sprintf ("user:%s" , ms ), nil
271308 }
272309 return "" , fmt .Errorf ("Failed to identify IAM member from BigQuery Dataset access: %v" , access )
273310}
0 commit comments