google-cloud-bigquery 1.24.0 → 1.25.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/google/cloud/bigquery/dataset/access.rb +110 -12
- data/lib/google/cloud/bigquery/policy.rb +431 -0
- data/lib/google/cloud/bigquery/service.rb +33 -0
- data/lib/google/cloud/bigquery/table.rb +102 -0
- data/lib/google/cloud/bigquery/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae4b6e4d7c37a945f027fe56425698b19b430f5e75451ce82f2156f2dae96719
|
4
|
+
data.tar.gz: d50284a47bf96d5221b574590a60b3af0f77b3a8943d201fd473d78f41a46670
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56c0b2d3214b385efb3866e502faa0b0c28c2fffc0c3d2ca3c5e1ad05f4d69e0638e68d59d8310c68d01c26c3db55b42225944379bfb8f6ad7a57eec558ced3a
|
7
|
+
data.tar.gz: 0562b98e65e880a40d634f541285241823354a966f4d05a559463a23eacca54addf8843f89b32731d313a56d91dfe2984f6098630c4126d7dbc97033d3dc6a81
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 1.25.0 / 2020-11-16
|
4
|
+
|
5
|
+
#### Features
|
6
|
+
|
7
|
+
* Add routine (UDF) to Dataset::Access
|
8
|
+
* Add support for Table ACLS (IAM Policy)
|
9
|
+
* feat(bigquery): Add support for Table ACLS
|
10
|
+
* Add Bigquery::Policy
|
11
|
+
* Add Table#policy
|
12
|
+
* Add Table#test_iam_permissions
|
13
|
+
* Add Table#update_policy
|
14
|
+
|
3
15
|
### 1.24.0 / 2020-10-29
|
4
16
|
|
5
17
|
#### Features
|
@@ -54,6 +54,7 @@ module Google
|
|
54
54
|
"groupByEmail" => :group_by_email,
|
55
55
|
"iam_member" => :iam_member,
|
56
56
|
"iamMember" => :iam_member,
|
57
|
+
"routine" => :routine,
|
57
58
|
"special" => :special_group,
|
58
59
|
"special_group" => :special_group,
|
59
60
|
"specialGroup" => :special_group,
|
@@ -212,6 +213,33 @@ module Google
|
|
212
213
|
add_access_role_scope_value :reader, :special, group
|
213
214
|
end
|
214
215
|
|
216
|
+
##
|
217
|
+
# Add access to a routine from a different dataset. Queries executed
|
218
|
+
# against that routine will have read access to views/tables/routines
|
219
|
+
# in this dataset. Only UDF is supported for now. The role field is
|
220
|
+
# not required when this field is set. If that routine is updated by
|
221
|
+
# any user, access to the routine needs to be granted again via an
|
222
|
+
# update operation.
|
223
|
+
#
|
224
|
+
# @param [Google::Cloud::Bigquery::Routine] routine A routine object.
|
225
|
+
#
|
226
|
+
# @example
|
227
|
+
# require "google/cloud/bigquery"
|
228
|
+
#
|
229
|
+
# bigquery = Google::Cloud::Bigquery.new
|
230
|
+
# dataset = bigquery.dataset "my_dataset"
|
231
|
+
# other_dataset = bigquery.dataset "my_other_dataset", skip_lookup: true
|
232
|
+
#
|
233
|
+
# routine = other_dataset.routine "my_routine"
|
234
|
+
#
|
235
|
+
# dataset.access do |access|
|
236
|
+
# access.add_reader_routine routine
|
237
|
+
# end
|
238
|
+
#
|
239
|
+
def add_reader_routine routine
|
240
|
+
add_access_routine routine
|
241
|
+
end
|
242
|
+
|
215
243
|
##
|
216
244
|
# Add reader access to a view.
|
217
245
|
#
|
@@ -227,9 +255,9 @@ module Google
|
|
227
255
|
#
|
228
256
|
# bigquery = Google::Cloud::Bigquery.new
|
229
257
|
# dataset = bigquery.dataset "my_dataset"
|
230
|
-
# other_dataset = bigquery.dataset "my_other_dataset"
|
258
|
+
# other_dataset = bigquery.dataset "my_other_dataset", skip_lookup: true
|
231
259
|
#
|
232
|
-
# view = other_dataset.table "my_view"
|
260
|
+
# view = other_dataset.table "my_view", skip_lookup: true
|
233
261
|
#
|
234
262
|
# dataset.access do |access|
|
235
263
|
# access.add_reader_view view
|
@@ -533,6 +561,28 @@ module Google
|
|
533
561
|
remove_access_role_scope_value :reader, :special, group
|
534
562
|
end
|
535
563
|
|
564
|
+
##
|
565
|
+
# Remove reader access from a routine from a different dataset.
|
566
|
+
#
|
567
|
+
# @param [Google::Cloud::Bigquery::Routine] routine A routine object.
|
568
|
+
#
|
569
|
+
# @example
|
570
|
+
# require "google/cloud/bigquery"
|
571
|
+
#
|
572
|
+
# bigquery = Google::Cloud::Bigquery.new
|
573
|
+
# dataset = bigquery.dataset "my_dataset"
|
574
|
+
# other_dataset = bigquery.dataset "my_other_dataset", skip_lookup: true
|
575
|
+
#
|
576
|
+
# routine = other_dataset.routine "my_routine", skip_lookup: true
|
577
|
+
#
|
578
|
+
# dataset.access do |access|
|
579
|
+
# access.remove_reader_routine routine
|
580
|
+
# end
|
581
|
+
#
|
582
|
+
def remove_reader_routine routine
|
583
|
+
remove_access_routine routine
|
584
|
+
end
|
585
|
+
|
536
586
|
##
|
537
587
|
# Remove reader access from a view.
|
538
588
|
#
|
@@ -548,9 +598,9 @@ module Google
|
|
548
598
|
#
|
549
599
|
# bigquery = Google::Cloud::Bigquery.new
|
550
600
|
# dataset = bigquery.dataset "my_dataset"
|
551
|
-
# other_dataset = bigquery.dataset "my_other_dataset"
|
601
|
+
# other_dataset = bigquery.dataset "my_other_dataset", skip_lookup: true
|
552
602
|
#
|
553
|
-
# view = other_dataset.table "my_view"
|
603
|
+
# view = other_dataset.table "my_view", skip_lookup: true
|
554
604
|
#
|
555
605
|
# dataset.access do |access|
|
556
606
|
# access.remove_reader_view view
|
@@ -849,6 +899,32 @@ module Google
|
|
849
899
|
lookup_access_role_scope_value :reader, :special, group
|
850
900
|
end
|
851
901
|
|
902
|
+
##
|
903
|
+
# Checks access for a routine from a different dataset. Queries executed
|
904
|
+
# against that routine will have read access to views/tables/routines
|
905
|
+
# in this dataset. Only UDF is supported for now. The role field is
|
906
|
+
# not required when this field is set. If that routine is updated by
|
907
|
+
# any user, access to the routine needs to be granted again via an
|
908
|
+
# update operation.
|
909
|
+
#
|
910
|
+
# @param [Google::Cloud::Bigquery::Routine] routine A routine object.
|
911
|
+
#
|
912
|
+
# @example
|
913
|
+
# require "google/cloud/bigquery"
|
914
|
+
#
|
915
|
+
# bigquery = Google::Cloud::Bigquery.new
|
916
|
+
# dataset = bigquery.dataset "my_dataset"
|
917
|
+
# other_dataset = bigquery.dataset "my_other_dataset", skip_lookup: true
|
918
|
+
#
|
919
|
+
# routine = other_dataset.routine "my_routine", skip_lookup: true
|
920
|
+
#
|
921
|
+
# access = dataset.access
|
922
|
+
# access.reader_routine? routine #=> false
|
923
|
+
#
|
924
|
+
def reader_routine? routine
|
925
|
+
lookup_access_routine routine
|
926
|
+
end
|
927
|
+
|
852
928
|
##
|
853
929
|
# Checks reader access for a view.
|
854
930
|
#
|
@@ -864,9 +940,9 @@ module Google
|
|
864
940
|
#
|
865
941
|
# bigquery = Google::Cloud::Bigquery.new
|
866
942
|
# dataset = bigquery.dataset "my_dataset"
|
867
|
-
# other_dataset = bigquery.dataset "my_other_dataset"
|
943
|
+
# other_dataset = bigquery.dataset "my_other_dataset", skip_lookup: true
|
868
944
|
#
|
869
|
-
# view = other_dataset.table "my_view"
|
945
|
+
# view = other_dataset.table "my_view", skip_lookup: true
|
870
946
|
#
|
871
947
|
# access = dataset.access
|
872
948
|
# access.reader_view? view #=> false
|
@@ -1121,12 +1197,22 @@ module Google
|
|
1121
1197
|
@rules << Google::Apis::BigqueryV2::Dataset::Access.new(opts)
|
1122
1198
|
end
|
1123
1199
|
|
1200
|
+
# @private
|
1201
|
+
def add_access_routine routine
|
1202
|
+
value = routine.routine_ref
|
1203
|
+
# Remove existing routine rule, if any
|
1204
|
+
@rules.reject!(&find_by_scope_and_resource_ref(:routine, value))
|
1205
|
+
# Add new rule for this role, scope, and value
|
1206
|
+
opts = { routine: value }
|
1207
|
+
@rules << Google::Apis::BigqueryV2::Dataset::Access.new(opts)
|
1208
|
+
end
|
1209
|
+
|
1124
1210
|
# @private
|
1125
1211
|
def add_access_view value
|
1126
1212
|
# scope is view, make sure value is in the right format
|
1127
1213
|
value = validate_view value
|
1128
1214
|
# Remove existing view rule, if any
|
1129
|
-
@rules.reject!(&
|
1215
|
+
@rules.reject!(&find_by_scope_and_resource_ref(:view, value))
|
1130
1216
|
# Add new rule for this role, scope, and value
|
1131
1217
|
opts = { view: value }
|
1132
1218
|
@rules << Google::Apis::BigqueryV2::Dataset::Access.new(opts)
|
@@ -1144,12 +1230,18 @@ module Google
|
|
1144
1230
|
)
|
1145
1231
|
end
|
1146
1232
|
|
1233
|
+
# @private
|
1234
|
+
def remove_access_routine routine
|
1235
|
+
# Remove existing routine rule, if any
|
1236
|
+
@rules.reject!(&find_by_scope_and_resource_ref(:routine, routine.routine_ref))
|
1237
|
+
end
|
1238
|
+
|
1147
1239
|
# @private
|
1148
1240
|
def remove_access_view value
|
1149
1241
|
# scope is view, make sure value is in the right format
|
1150
1242
|
value = validate_view value
|
1151
1243
|
# Remove existing view rule, if any
|
1152
|
-
@rules.reject!(&
|
1244
|
+
@rules.reject!(&find_by_scope_and_resource_ref(:view, value))
|
1153
1245
|
end
|
1154
1246
|
|
1155
1247
|
# @private
|
@@ -1162,12 +1254,18 @@ module Google
|
|
1162
1254
|
!(!@rules.detect(&find_by_role_and_scope_and_value(role, scope, value)))
|
1163
1255
|
end
|
1164
1256
|
|
1257
|
+
# @private
|
1258
|
+
def lookup_access_routine routine
|
1259
|
+
# Detect routine rule, if any
|
1260
|
+
!(!@rules.detect(&find_by_scope_and_resource_ref(:routine, routine.routine_ref)))
|
1261
|
+
end
|
1262
|
+
|
1165
1263
|
# @private
|
1166
1264
|
def lookup_access_view value
|
1167
1265
|
# scope is view, make sure value is in the right format
|
1168
1266
|
value = validate_view value
|
1169
1267
|
# Detect view rule, if any
|
1170
|
-
!(!@rules.detect(&
|
1268
|
+
!(!@rules.detect(&find_by_scope_and_resource_ref(:view, value)))
|
1171
1269
|
end
|
1172
1270
|
|
1173
1271
|
# @private
|
@@ -1186,11 +1284,11 @@ module Google
|
|
1186
1284
|
end
|
1187
1285
|
end
|
1188
1286
|
|
1189
|
-
# @private
|
1190
|
-
def
|
1287
|
+
# @private Compare hash representations to find table_ref, routine_ref.
|
1288
|
+
def find_by_scope_and_resource_ref scope, value
|
1191
1289
|
lambda do |a|
|
1192
1290
|
h = a.to_h
|
1193
|
-
h[
|
1291
|
+
h[scope].to_h == value.to_h
|
1194
1292
|
end
|
1195
1293
|
end
|
1196
1294
|
end
|
@@ -0,0 +1,431 @@
|
|
1
|
+
# Copyright 2020 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "google/apis/bigquery_v2"
|
17
|
+
|
18
|
+
module Google
|
19
|
+
module Cloud
|
20
|
+
module Bigquery
|
21
|
+
##
|
22
|
+
# # Policy
|
23
|
+
#
|
24
|
+
# Represents a Cloud IAM Policy for BigQuery resources.
|
25
|
+
#
|
26
|
+
# A Policy is a collection of bindings. A {Policy::Binding} binds one or more members to a single role. Member
|
27
|
+
# strings can describe user accounts, service accounts, Google groups, and domains. A role string represents a
|
28
|
+
# named list of permissions; each role can be an IAM predefined role or a user-created custom role.
|
29
|
+
#
|
30
|
+
# @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
|
31
|
+
# @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
|
32
|
+
#
|
33
|
+
# @attr [String] etag Used to check if the policy has changed since the last request. When you make a request with
|
34
|
+
# an `etag` value, Cloud IAM compares the `etag` value in the request with the existing `etag` value associated
|
35
|
+
# with the policy. It writes the policy only if the `etag` values match.
|
36
|
+
# @attr [Array<Binding>] bindings The bindings in the policy, which may be mutable or frozen depending on the
|
37
|
+
# context. See [Understanding Roles](https://cloud.google.com/iam/docs/understanding-roles) for a list of
|
38
|
+
# primitive and curated roles. See [BigQuery Table ACL
|
39
|
+
# permissions](https://cloud.google.com/bigquery/docs/table-access-controls-intro#permissions) for a list of
|
40
|
+
# values and patterns for members.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# require "google/cloud/bigquery"
|
44
|
+
#
|
45
|
+
# bigquery = Google::Cloud::Bigquery.new
|
46
|
+
# dataset = bigquery.dataset "my_dataset"
|
47
|
+
# table = dataset.table "my_table"
|
48
|
+
# policy = table.policy
|
49
|
+
#
|
50
|
+
# policy.frozen? #=> true
|
51
|
+
# binding_owner = policy.bindings.find { |b| b.role == "roles/owner" }
|
52
|
+
#
|
53
|
+
# binding_owner.role #=> "roles/owner"
|
54
|
+
# binding_owner.members #=> ["user:owner@example.com"]
|
55
|
+
# binding_owner.frozen? #=> true
|
56
|
+
# binding_owner.members.frozen? #=> true
|
57
|
+
#
|
58
|
+
# @example Update mutable bindings in the policy.
|
59
|
+
# require "google/cloud/bigquery"
|
60
|
+
#
|
61
|
+
# bigquery = Google::Cloud::Bigquery.new
|
62
|
+
# dataset = bigquery.dataset "my_dataset"
|
63
|
+
# table = dataset.table "my_table"
|
64
|
+
#
|
65
|
+
# table.update_policy do |p|
|
66
|
+
# p.grant role: "roles/viewer", members: "user:viewer@example.com"
|
67
|
+
# p.revoke role: "roles/editor", members: "user:editor@example.com"
|
68
|
+
# p.revoke role: "roles/owner"
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# @example Iterate over frozen bindings.
|
72
|
+
# require "google/cloud/bigquery"
|
73
|
+
#
|
74
|
+
# bigquery = Google::Cloud::Bigquery.new
|
75
|
+
# dataset = bigquery.dataset "my_dataset"
|
76
|
+
# table = dataset.table "my_table"
|
77
|
+
# policy = table.policy
|
78
|
+
#
|
79
|
+
# policy.frozen? #=> true
|
80
|
+
# policy.bindings.each do |b|
|
81
|
+
# puts b.role
|
82
|
+
# puts b.members
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
# @example Update mutable bindings.
|
86
|
+
# require "google/cloud/bigquery"
|
87
|
+
#
|
88
|
+
# bigquery = Google::Cloud::Bigquery.new
|
89
|
+
# dataset = bigquery.dataset "my_dataset"
|
90
|
+
# table = dataset.table "my_table"
|
91
|
+
#
|
92
|
+
# table.update_policy do |p|
|
93
|
+
# p.bindings.each do |b|
|
94
|
+
# b.members.delete_if { |m| m.include? "@example.com" }
|
95
|
+
# end
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
class Policy
|
99
|
+
attr_reader :etag, :bindings
|
100
|
+
|
101
|
+
# @private
|
102
|
+
def initialize etag, bindings
|
103
|
+
@etag = etag.freeze
|
104
|
+
@bindings = bindings
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Convenience method adding or updating a binding in the policy. See [Understanding
|
109
|
+
# Roles](https://cloud.google.com/iam/docs/understanding-roles) for a list of primitive and curated roles. See
|
110
|
+
# [BigQuery Table ACL
|
111
|
+
# permissions](https://cloud.google.com/bigquery/docs/table-access-controls-intro#permissions) for a list of
|
112
|
+
# values and patterns for members.
|
113
|
+
#
|
114
|
+
# @param [String] role The role that is bound to members in the binding. For example, `roles/viewer`,
|
115
|
+
# `roles/editor`, or `roles/owner`. Required.
|
116
|
+
# @param [String, Array<String>] members Specifies the identities requesting access for a Cloud Platform
|
117
|
+
# resource. `members` can have the following values. Required.
|
118
|
+
#
|
119
|
+
# * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
|
120
|
+
# account.
|
121
|
+
# * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
|
122
|
+
# account or a service account.
|
123
|
+
# * `user:<emailid>`: An email address that represents a specific Google account. For example,
|
124
|
+
# `alice@example.com`.
|
125
|
+
# * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
|
126
|
+
# `my-other-app@appspot.gserviceaccount.com`.
|
127
|
+
# * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
|
128
|
+
# * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
|
129
|
+
# that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
|
130
|
+
# is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
|
131
|
+
# binding.
|
132
|
+
# * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing
|
133
|
+
# a service account that has been recently deleted. For example,
|
134
|
+
# `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is undeleted,
|
135
|
+
# this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains the role in
|
136
|
+
# the binding.
|
137
|
+
# * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a Google
|
138
|
+
# group that has been recently deleted. For example, `admins@example.com?uid=123456789012345678901`. If the
|
139
|
+
# group is recovered, this value reverts to `group:<emailid>` and the recovered group retains the role in
|
140
|
+
# the binding.
|
141
|
+
# * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For example,
|
142
|
+
# `google.com` or `example.com`.
|
143
|
+
#
|
144
|
+
# @return [nil]
|
145
|
+
#
|
146
|
+
# @example Grant a role to a member.
|
147
|
+
# require "google/cloud/bigquery"
|
148
|
+
#
|
149
|
+
# bigquery = Google::Cloud::Bigquery.new
|
150
|
+
# dataset = bigquery.dataset "my_dataset"
|
151
|
+
# table = dataset.table "my_table"
|
152
|
+
#
|
153
|
+
# table.update_policy do |p|
|
154
|
+
# p.grant role: "roles/viewer", members: "user:viewer@example.com"
|
155
|
+
# end
|
156
|
+
#
|
157
|
+
def grant role:, members:
|
158
|
+
existing_binding = bindings.find { |b| b.role == role }
|
159
|
+
if existing_binding
|
160
|
+
existing_binding.members.concat Array(members)
|
161
|
+
existing_binding.members.uniq!
|
162
|
+
else
|
163
|
+
bindings << Binding.new(role, members)
|
164
|
+
end
|
165
|
+
nil
|
166
|
+
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# Convenience method for removing a binding or bindings from the policy. See
|
170
|
+
# [Understanding Roles](https://cloud.google.com/iam/docs/understanding-roles) for a list of primitive and
|
171
|
+
# curated roles. See [BigQuery Table ACL
|
172
|
+
# permissions](https://cloud.google.com/bigquery/docs/table-access-controls-intro#permissions) for a list of
|
173
|
+
# values and patterns for members.
|
174
|
+
#
|
175
|
+
# @param [String] role A role that is bound to members in the policy. For example, `roles/viewer`,
|
176
|
+
# `roles/editor`, or `roles/owner`. Optional.
|
177
|
+
# @param [String, Array<String>] members Specifies the identities receiving access for a Cloud Platform
|
178
|
+
# resource. `members` can have the following values. Optional.
|
179
|
+
#
|
180
|
+
# * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
|
181
|
+
# account.
|
182
|
+
# * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
|
183
|
+
# account or a service account.
|
184
|
+
# * `user:<emailid>`: An email address that represents a specific Google account. For example,
|
185
|
+
# `alice@example.com`.
|
186
|
+
# * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
|
187
|
+
# `my-other-app@appspot.gserviceaccount.com`.
|
188
|
+
# * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
|
189
|
+
# * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
|
190
|
+
# that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
|
191
|
+
# is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
|
192
|
+
# binding.
|
193
|
+
# * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing
|
194
|
+
# a service account that has been recently deleted. For example,
|
195
|
+
# `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is undeleted,
|
196
|
+
# this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains the role in
|
197
|
+
# the binding.
|
198
|
+
# * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a Google
|
199
|
+
# group that has been recently deleted. For example, `admins@example.com?uid=123456789012345678901`. If the
|
200
|
+
# group is recovered, this value reverts to `group:<emailid>` and the recovered group retains the role in
|
201
|
+
# the binding.
|
202
|
+
# * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For example,
|
203
|
+
# `google.com` or `example.com`.
|
204
|
+
#
|
205
|
+
# @return [nil]
|
206
|
+
#
|
207
|
+
# @example Revoke a role for a member or members.
|
208
|
+
# require "google/cloud/bigquery"
|
209
|
+
#
|
210
|
+
# bigquery = Google::Cloud::Bigquery.new
|
211
|
+
# dataset = bigquery.dataset "my_dataset"
|
212
|
+
# table = dataset.table "my_table"
|
213
|
+
#
|
214
|
+
# table.update_policy do |p|
|
215
|
+
# p.revoke role: "roles/viewer", members: "user:viewer@example.com"
|
216
|
+
# end
|
217
|
+
#
|
218
|
+
# @example Revoke a role for all members.
|
219
|
+
# require "google/cloud/bigquery"
|
220
|
+
#
|
221
|
+
# bigquery = Google::Cloud::Bigquery.new
|
222
|
+
# dataset = bigquery.dataset "my_dataset"
|
223
|
+
# table = dataset.table "my_table"
|
224
|
+
#
|
225
|
+
# table.update_policy do |p|
|
226
|
+
# p.revoke role: "roles/viewer"
|
227
|
+
# end
|
228
|
+
#
|
229
|
+
# @example Revoke all roles for a member or members.
|
230
|
+
# require "google/cloud/bigquery"
|
231
|
+
#
|
232
|
+
# bigquery = Google::Cloud::Bigquery.new
|
233
|
+
# dataset = bigquery.dataset "my_dataset"
|
234
|
+
# table = dataset.table "my_table"
|
235
|
+
#
|
236
|
+
# table.update_policy do |p|
|
237
|
+
# p.revoke members: ["user:viewer@example.com", "user:editor@example.com"]
|
238
|
+
# end
|
239
|
+
#
|
240
|
+
def revoke role: nil, members: nil
|
241
|
+
bindings_for_role = role ? bindings.select { |b| b.role == role } : bindings
|
242
|
+
bindings_for_role.each do |b|
|
243
|
+
if members
|
244
|
+
b.members -= Array(members)
|
245
|
+
bindings.delete b if b.members.empty?
|
246
|
+
else
|
247
|
+
bindings.delete b
|
248
|
+
end
|
249
|
+
end
|
250
|
+
nil
|
251
|
+
end
|
252
|
+
|
253
|
+
##
|
254
|
+
# @private Convert the Policy to a Google::Apis::BigqueryV2::Policy.
|
255
|
+
def to_gapi
|
256
|
+
Google::Apis::BigqueryV2::Policy.new(
|
257
|
+
bindings: bindings_to_gapi,
|
258
|
+
etag: etag,
|
259
|
+
version: 1
|
260
|
+
)
|
261
|
+
end
|
262
|
+
|
263
|
+
##
|
264
|
+
# @private Deep freeze the policy including its bindings.
|
265
|
+
def freeze
|
266
|
+
super
|
267
|
+
@bindings.each(&:freeze)
|
268
|
+
@bindings.freeze
|
269
|
+
self
|
270
|
+
end
|
271
|
+
|
272
|
+
##
|
273
|
+
# @private New Policy from a Google::Apis::BigqueryV2::Policy object.
|
274
|
+
def self.from_gapi gapi
|
275
|
+
bindings = Array(gapi.bindings).map do |binding|
|
276
|
+
Binding.new binding.role, binding.members.to_a
|
277
|
+
end
|
278
|
+
new gapi.etag, bindings
|
279
|
+
end
|
280
|
+
|
281
|
+
##
|
282
|
+
# # Policy::Binding
|
283
|
+
#
|
284
|
+
# Represents a Cloud IAM Binding for BigQuery resources within the context of a {Policy}.
|
285
|
+
#
|
286
|
+
# A binding binds one or more members to a single role. Member strings can describe user accounts, service
|
287
|
+
# accounts, Google groups, and domains. A role is a named list of permissions; each role can be an IAM
|
288
|
+
# predefined role or a user-created custom role.
|
289
|
+
#
|
290
|
+
# @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
|
291
|
+
#
|
292
|
+
# @attr [String] role The role that is assigned to `members`. For example, `roles/viewer`, `roles/editor`, or
|
293
|
+
# `roles/owner`. Required.
|
294
|
+
# @attr [Array<String>] members Specifies the identities requesting access for a Cloud Platform resource.
|
295
|
+
# `members` can have the following values. Required.
|
296
|
+
#
|
297
|
+
# * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
|
298
|
+
# account.
|
299
|
+
# * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
|
300
|
+
# account or a service account.
|
301
|
+
# * `user:<emailid>`: An email address that represents a specific Google account. For example,
|
302
|
+
# `alice@example.com`.
|
303
|
+
# * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
|
304
|
+
# `my-other-app@appspot.gserviceaccount.com`.
|
305
|
+
# * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
|
306
|
+
# * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
|
307
|
+
# that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
|
308
|
+
# is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
|
309
|
+
# binding.
|
310
|
+
# * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing
|
311
|
+
# a service account that has been recently deleted. For example,
|
312
|
+
# `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is undeleted,
|
313
|
+
# this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains the role in
|
314
|
+
# the binding.
|
315
|
+
# * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a Google
|
316
|
+
# group that has been recently deleted. For example, `admins@example.com?uid=123456789012345678901`. If the
|
317
|
+
# group is recovered, this value reverts to `group:<emailid>` and the recovered group retains the role in
|
318
|
+
# the binding.
|
319
|
+
# * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For example,
|
320
|
+
# `google.com` or `example.com`.
|
321
|
+
#
|
322
|
+
# @example
|
323
|
+
# require "google/cloud/bigquery"
|
324
|
+
#
|
325
|
+
# bigquery = Google::Cloud::Bigquery.new
|
326
|
+
# dataset = bigquery.dataset "my_dataset"
|
327
|
+
# table = dataset.table "my_table"
|
328
|
+
#
|
329
|
+
# policy = table.policy
|
330
|
+
# binding_owner = policy.bindings.find { |b| b.role == "roles/owner" }
|
331
|
+
#
|
332
|
+
# binding_owner.role #=> "roles/owner"
|
333
|
+
# binding_owner.members #=> ["user:owner@example.com"]
|
334
|
+
#
|
335
|
+
# binding_owner.frozen? #=> true
|
336
|
+
# binding_owner.members.frozen? #=> true
|
337
|
+
#
|
338
|
+
# @example Update mutable bindings.
|
339
|
+
# require "google/cloud/bigquery"
|
340
|
+
#
|
341
|
+
# bigquery = Google::Cloud::Bigquery.new
|
342
|
+
# dataset = bigquery.dataset "my_dataset"
|
343
|
+
# table = dataset.table "my_table"
|
344
|
+
#
|
345
|
+
# table.update_policy do |p|
|
346
|
+
# binding_owner = p.bindings.find { |b| b.role == "roles/owner" }
|
347
|
+
# binding_owner.members.delete_if { |m| m.include? "@example.com" }
|
348
|
+
# end
|
349
|
+
#
|
350
|
+
class Binding
|
351
|
+
attr_accessor :role
|
352
|
+
attr_reader :members
|
353
|
+
|
354
|
+
# @private
|
355
|
+
def initialize role, members
|
356
|
+
members = Array(members).uniq
|
357
|
+
raise ArgumentError, "members cannot be empty" if members.empty?
|
358
|
+
@role = role
|
359
|
+
@members = members
|
360
|
+
end
|
361
|
+
|
362
|
+
##
|
363
|
+
# Sets the binding members.
|
364
|
+
#
|
365
|
+
# @param [Array<String>] new_members Specifies the identities requesting access for a Cloud Platform resource.
|
366
|
+
# `new_members` can have the following values. Required.
|
367
|
+
#
|
368
|
+
# * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
|
369
|
+
# account.
|
370
|
+
# * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
|
371
|
+
# account or a service account.
|
372
|
+
# * `user:<emailid>`: An email address that represents a specific Google account. For example,
|
373
|
+
# `alice@example.com`.
|
374
|
+
# * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
|
375
|
+
# `my-other-app@appspot.gserviceaccount.com`.
|
376
|
+
# * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
|
377
|
+
# * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
|
378
|
+
# that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
|
379
|
+
# is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
|
380
|
+
# binding.
|
381
|
+
# * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier)
|
382
|
+
# representing a service account that has been recently deleted. For example,
|
383
|
+
# `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is
|
384
|
+
# undeleted, this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains
|
385
|
+
# the role in the binding.
|
386
|
+
# * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a
|
387
|
+
# Google group that has been recently deleted. For example,
|
388
|
+
# `admins@example.com?uid=123456789012345678901`. If the group is recovered, this value reverts to
|
389
|
+
# `group:<emailid>` and the recovered group retains the role in the binding.
|
390
|
+
# * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For
|
391
|
+
# example, `google.com` or `example.com`.
|
392
|
+
#
|
393
|
+
def members= new_members
|
394
|
+
@members = Array(new_members).uniq
|
395
|
+
end
|
396
|
+
|
397
|
+
##
|
398
|
+
# @private Convert the Binding to a Google::Apis::BigqueryV2::Binding.
|
399
|
+
def to_gapi
|
400
|
+
Google::Apis::BigqueryV2::Binding.new role: role, members: members
|
401
|
+
end
|
402
|
+
|
403
|
+
##
|
404
|
+
# @private Deep freeze the policy including its members.
|
405
|
+
def freeze
|
406
|
+
super
|
407
|
+
role.freeze
|
408
|
+
members.each(&:freeze)
|
409
|
+
members.freeze
|
410
|
+
self
|
411
|
+
end
|
412
|
+
|
413
|
+
##
|
414
|
+
# @private New Binding from a Google::Apis::BigqueryV2::Binding object.
|
415
|
+
def self.from_gapi gapi
|
416
|
+
new gapi.etag, gapi.members.to_a
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
protected
|
421
|
+
|
422
|
+
def bindings_to_gapi
|
423
|
+
@bindings.compact.uniq.map do |b|
|
424
|
+
next if b.members.empty?
|
425
|
+
b.to_gapi
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|
@@ -182,6 +182,34 @@ module Google
|
|
182
182
|
end
|
183
183
|
end
|
184
184
|
|
185
|
+
##
|
186
|
+
# Returns Google::Apis::BigqueryV2::Policy
|
187
|
+
def get_table_policy dataset_id, table_id
|
188
|
+
policy_options = API::GetPolicyOptions.new requested_policy_version: 1
|
189
|
+
execute do
|
190
|
+
service.get_table_iam_policy table_path(dataset_id, table_id),
|
191
|
+
API::GetIamPolicyRequest.new(options: policy_options)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
##
|
196
|
+
# @param [Google::Apis::BigqueryV2::Policy] new_policy
|
197
|
+
def set_table_policy dataset_id, table_id, new_policy
|
198
|
+
execute do
|
199
|
+
service.set_table_iam_policy table_path(dataset_id, table_id),
|
200
|
+
API::SetIamPolicyRequest.new(policy: new_policy)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
##
|
205
|
+
# Returns Google::Apis::BigqueryV2::TestIamPermissionsResponse
|
206
|
+
def test_table_permissions dataset_id, table_id, permissions
|
207
|
+
execute do
|
208
|
+
service.test_table_iam_permissions table_path(dataset_id, table_id),
|
209
|
+
API::TestIamPermissionsRequest.new(permissions: permissions)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
185
213
|
##
|
186
214
|
# Deletes the table specified by tableId from the dataset.
|
187
215
|
# If the table contains data, all the data will be deleted.
|
@@ -508,6 +536,11 @@ module Google
|
|
508
536
|
|
509
537
|
protected
|
510
538
|
|
539
|
+
# Creates a formatted table path.
|
540
|
+
def table_path dataset_id, table_id
|
541
|
+
"projects/#{@project}/datasets/#{dataset_id}/tables/#{table_id}"
|
542
|
+
end
|
543
|
+
|
511
544
|
# Generate a random string similar to the BigQuery service job IDs.
|
512
545
|
def generate_id
|
513
546
|
SecureRandom.urlsafe_base64 21
|
@@ -23,6 +23,7 @@ require "google/cloud/bigquery/external"
|
|
23
23
|
require "google/cloud/bigquery/insert_response"
|
24
24
|
require "google/cloud/bigquery/table/async_inserter"
|
25
25
|
require "google/cloud/bigquery/convert"
|
26
|
+
require "google/cloud/bigquery/policy"
|
26
27
|
require "google/apis/bigquery_v2"
|
27
28
|
|
28
29
|
module Google
|
@@ -1274,6 +1275,107 @@ module Google
|
|
1274
1275
|
Array(udfs_gapi).map { |udf| udf.inline_code || udf.resource_uri }
|
1275
1276
|
end
|
1276
1277
|
|
1278
|
+
##
|
1279
|
+
# Gets the Cloud IAM access control policy for the table. The latest policy will be read from the service. See
|
1280
|
+
# also {#update_policy}.
|
1281
|
+
#
|
1282
|
+
# @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
|
1283
|
+
# @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
|
1284
|
+
#
|
1285
|
+
# @return [Policy] The frozen policy for the table.
|
1286
|
+
#
|
1287
|
+
# @example
|
1288
|
+
# require "google/cloud/bigquery"
|
1289
|
+
#
|
1290
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1291
|
+
# dataset = bigquery.dataset "my_dataset"
|
1292
|
+
# table = dataset.table "my_table"
|
1293
|
+
#
|
1294
|
+
# policy = table.policy
|
1295
|
+
#
|
1296
|
+
# policy.frozen? #=> true
|
1297
|
+
# binding_owner = policy.bindings.find { |b| b.role == "roles/owner" }
|
1298
|
+
# binding_owner.role #=> "roles/owner"
|
1299
|
+
# binding_owner.members #=> ["user:owner@example.com"]
|
1300
|
+
# binding_owner.frozen? #=> true
|
1301
|
+
# binding_owner.members.frozen? #=> true
|
1302
|
+
#
|
1303
|
+
def policy
|
1304
|
+
raise ArgumentError, "Block argument not supported: Use #update_policy instead." if block_given?
|
1305
|
+
ensure_service!
|
1306
|
+
gapi = service.get_table_policy dataset_id, table_id
|
1307
|
+
Policy.from_gapi(gapi).freeze
|
1308
|
+
end
|
1309
|
+
|
1310
|
+
##
|
1311
|
+
# Updates the Cloud IAM access control policy for the table. The latest policy will be read from the service.
|
1312
|
+
# See also {#policy}.
|
1313
|
+
#
|
1314
|
+
# @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
|
1315
|
+
# @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
|
1316
|
+
#
|
1317
|
+
# @yield [policy] A block for updating the policy. The latest policy will be read from the service and passed to
|
1318
|
+
# the block. After the block completes, the modified policy will be written to the service.
|
1319
|
+
# @yieldparam [Policy] policy The mutable Policy for the table.
|
1320
|
+
#
|
1321
|
+
# @return [Policy] The updated and frozen policy for the table.
|
1322
|
+
#
|
1323
|
+
# @example Update the policy by passing a block.
|
1324
|
+
# require "google/cloud/bigquery"
|
1325
|
+
#
|
1326
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1327
|
+
# dataset = bigquery.dataset "my_dataset"
|
1328
|
+
# table = dataset.table "my_table"
|
1329
|
+
#
|
1330
|
+
# table.update_policy do |p|
|
1331
|
+
# p.grant role: "roles/viewer", members: "user:viewer@example.com"
|
1332
|
+
# p.revoke role: "roles/editor", members: "user:editor@example.com"
|
1333
|
+
# p.revoke role: "roles/owner"
|
1334
|
+
# end # 2 API calls
|
1335
|
+
#
|
1336
|
+
def update_policy
|
1337
|
+
raise ArgumentError, "A block updating the policy must be provided" unless block_given?
|
1338
|
+
ensure_service!
|
1339
|
+
gapi = service.get_table_policy dataset_id, table_id
|
1340
|
+
policy = Policy.from_gapi gapi
|
1341
|
+
yield policy
|
1342
|
+
# TODO: Check for changes before calling RPC
|
1343
|
+
gapi = service.set_table_policy dataset_id, table_id, policy.to_gapi
|
1344
|
+
Policy.from_gapi(gapi).freeze
|
1345
|
+
end
|
1346
|
+
|
1347
|
+
##
|
1348
|
+
# Tests the specified permissions against the [Cloud
|
1349
|
+
# IAM](https://cloud.google.com/iam/) access control policy.
|
1350
|
+
#
|
1351
|
+
# @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
|
1352
|
+
#
|
1353
|
+
# @param [String, Array<String>] permissions The set of permissions
|
1354
|
+
# against which to check access. Permissions must be of the format
|
1355
|
+
# `bigquery.resource.capability`.
|
1356
|
+
# See https://cloud.google.com/bigquery/docs/access-control#bigquery.
|
1357
|
+
#
|
1358
|
+
# @return [Array<String>] The frozen array of permissions held by the caller.
|
1359
|
+
#
|
1360
|
+
# @example
|
1361
|
+
# require "google/cloud/bigquery"
|
1362
|
+
#
|
1363
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1364
|
+
# dataset = bigquery.dataset "my_dataset"
|
1365
|
+
# table = dataset.table "my_table"
|
1366
|
+
#
|
1367
|
+
# permissions = table.test_iam_permissions "bigquery.tables.get",
|
1368
|
+
# "bigquery.tables.delete"
|
1369
|
+
# permissions.include? "bigquery.tables.get" #=> true
|
1370
|
+
# permissions.include? "bigquery.tables.delete" #=> false
|
1371
|
+
#
|
1372
|
+
def test_iam_permissions *permissions
|
1373
|
+
permissions = Array(permissions).flatten
|
1374
|
+
ensure_service!
|
1375
|
+
gapi = service.test_table_permissions dataset_id, table_id, permissions
|
1376
|
+
gapi.permissions.freeze
|
1377
|
+
end
|
1378
|
+
|
1277
1379
|
##
|
1278
1380
|
# Retrieves data from the table.
|
1279
1381
|
#
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google-cloud-bigquery
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.25.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Moore
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-11-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: concurrent-ruby
|
@@ -257,6 +257,7 @@ files:
|
|
257
257
|
- lib/google/cloud/bigquery/load_job.rb
|
258
258
|
- lib/google/cloud/bigquery/model.rb
|
259
259
|
- lib/google/cloud/bigquery/model/list.rb
|
260
|
+
- lib/google/cloud/bigquery/policy.rb
|
260
261
|
- lib/google/cloud/bigquery/project.rb
|
261
262
|
- lib/google/cloud/bigquery/project/list.rb
|
262
263
|
- lib/google/cloud/bigquery/query_job.rb
|