Skip to content

Commit d181b22

Browse files
authored
samples(storage): IAM conditions samples (GoogleCloudPlatform#1018)
1 parent f01e637 commit d181b22

7 files changed

+274
-85
lines changed

storage/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
22
"require": {
3-
"google/cloud-storage": "^1.14.0",
3+
"google/cloud-storage": "^1.18.0",
44
"paragonie/random_compat": "^2.0",
55
"symfony/console": " ^3.0"
66
},
77
"autoload": {
88
"files": [
99
"src/add_bucket_acl.php",
10+
"src/add_bucket_conditional_iam_binding.php",
1011
"src/add_bucket_default_acl.php",
1112
"src/add_bucket_iam_member.php",
1213
"src/add_bucket_label.php",
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
2+
/**
3+
* Copyright 2020 Google Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
/**
19+
* For instructions on how to run the full sample:
20+
*
21+
* @see https://github.com/GoogleCloudPlatform/php-docs-samples/tree/master/storage/README.md
22+
*/
23+
24+
namespace Google\Cloud\Samples\Storage;
25+
26+
# [START add_bucket_conditional_iam_binding]
27+
use Google\Cloud\Storage\StorageClient;
28+
29+
/**
30+
* Adds a conditional IAM binding to a bucket's IAM policy.
31+
*
32+
* @param string $bucketName the name of your Cloud Storage bucket.
33+
* @param string $role the role that will be given to members in this binding.
34+
* @param string[] $members the member(s) that is associated to this binding.
35+
* @param string $title condition's title
36+
* @param string $description condition's description
37+
* @param string $expression the condition specified in CEL expression language.
38+
*
39+
* To see how to express a condition in CEL, visit:
40+
* @see https://cloud.google.com/storage/docs/access-control/iam#conditions.
41+
*
42+
* @return void
43+
*/
44+
function add_bucket_conditional_iam_binding($bucketName, $role, $members, $title, $description, $expression)
45+
{
46+
$storage = new StorageClient();
47+
$bucket = $storage->bucket($bucketName);
48+
49+
$policy = $bucket->iam()->policy(['requestedPolicyVersion' => 3]);
50+
51+
$policy['version'] = 3;
52+
53+
$policy['bindings'][] = [
54+
'role' => $role,
55+
'members' => $members,
56+
'condition' => [
57+
'title' => $title,
58+
'description' => $description,
59+
'expression' => $expression,
60+
],
61+
];
62+
63+
$bucket->iam()->setPolicy($policy);
64+
65+
printf('Added the following member(s) with role %s to %s:' . PHP_EOL, $role, $bucketName);
66+
foreach ($members as $member) {
67+
printf(' %s' . PHP_EOL, $member);
68+
}
69+
printf('with condition:' . PHP_EOL);
70+
printf(' Title: %s' . PHP_EOL, $title);
71+
printf(' Description: %s' . PHP_EOL, $description);
72+
printf(' Expression: %s' . PHP_EOL, $expression);
73+
}
74+
# [END add_bucket_conditional_iam_binding]

storage/src/add_bucket_iam_member.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,29 @@
3131
*
3232
* @param string $bucketName the name of your Cloud Storage bucket.
3333
* @param string $role the role you want to add a given member to.
34-
* @param string $member the member you want to give the new role for the Cloud
34+
* @param string[] $members the member(s) you want to give the new role for the Cloud
3535
* Storage bucket.
3636
*
3737
* @return void
3838
*/
39-
function add_bucket_iam_member($bucketName, $role, $member)
39+
function add_bucket_iam_member($bucketName, $role, $members)
4040
{
4141
$storage = new StorageClient();
4242
$bucket = $storage->bucket($bucketName);
4343

44-
$policy = $bucket->iam()->policy();
44+
$policy = $bucket->iam()->policy(['requestedPolicyVersion' => 3]);
45+
$policy['version'] = 3;
4546

4647
$policy['bindings'][] = [
4748
'role' => $role,
48-
'members' => [$member]
49+
'members' => $members
4950
];
5051

5152
$bucket->iam()->setPolicy($policy);
5253

53-
printf('User %s added to role %s for bucket %s' . PHP_EOL, $member, $role, $bucketName);
54+
printf('Added the following member(s) to role %s for bucket %s' . PHP_EOL, $role, $bucketName);
55+
foreach ($members as $member) {
56+
printf(' %s' . PHP_EOL, $member);
57+
}
5458
}
5559
# [END add_bucket_iam_member]

storage/src/remove_bucket_iam_member.php

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
namespace Google\Cloud\Samples\Storage;
2525

2626
# [START remove_bucket_iam_member]
27-
use Google\Cloud\Core\Iam\PolicyBuilder;
2827
use Google\Cloud\Storage\StorageClient;
2928

3029
/**
@@ -40,11 +39,30 @@ function remove_bucket_iam_member($bucketName, $role, $member)
4039
{
4140
$storage = new StorageClient();
4241
$bucket = $storage->bucket($bucketName);
43-
$policy = $bucket->iam()->policy();
44-
$policyBuilder = new PolicyBuilder($policy);
45-
$policyBuilder->removeBinding($role, [$member]);
42+
$iam = $bucket->iam();
43+
$policy = $iam->policy(['requestedPolicyVersion' => 3]);
44+
$policy['version'] = 3;
4645

47-
$bucket->iam()->setPolicy($policyBuilder->result());
48-
printf('User %s removed from role %s for bucket %s' . PHP_EOL, $member, $role, $bucketName);
46+
foreach ($policy['bindings'] as $i => $binding) {
47+
// This example only removes member from bindings without a condition.
48+
if ($binding['role'] == $role && !isset($binding['condition'])) {
49+
$key = array_search($member, $binding['members']);
50+
if ($key !== false) {
51+
unset($binding['members'][$key]);
52+
53+
// If the last member is removed from the binding, clean up
54+
// the binding.
55+
if (count($binding['members']) == 0) {
56+
unset($policy['bindings'][$i]);
57+
}
58+
59+
$iam->setPolicy($policy);
60+
printf('User %s removed from role %s for bucket %s' . PHP_EOL, $member, $role, $bucketName);
61+
return;
62+
}
63+
}
64+
}
65+
66+
throw new \RuntimeException('No matching role-member group(s) found.');
4967
}
5068
# [END remove_bucket_iam_member]

storage/src/view_bucket_iam_members.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ function view_bucket_iam_members($bucketName)
3838
$storage = new StorageClient();
3939
$bucket = $storage->bucket($bucketName);
4040

41-
$policy = $bucket->iam()->policy();
41+
$policy = $bucket->iam()->policy(['requestedPolicyVersion' => 3]);
4242

4343
printf('Printing Bucket IAM members for Bucket: %s' . PHP_EOL, $bucketName);
4444
printf(PHP_EOL);
@@ -49,6 +49,14 @@ function view_bucket_iam_members($bucketName)
4949
foreach ($binding['members'] as $member) {
5050
printf(' %s' . PHP_EOL, $member);
5151
}
52+
53+
if (isset($binding['condition'])) {
54+
$condition = $binding['condition'];
55+
printf(' with condition:' . PHP_EOL);
56+
printf(' Title: %s' . PHP_EOL, $condition['title']);
57+
printf(' Description: %s' . PHP_EOL, $condition['description']);
58+
printf(' Expression: %s' . PHP_EOL, $condition['expression']);
59+
}
5260
printf(PHP_EOL);
5361
}
5462
}

storage/storage.php

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -265,26 +265,37 @@
265265
266266
php %command.full_name% my-bucket
267267
268-
php %command.full_name% my-bucket --role my-role --add-member user/test@email.com
268+
php %command.full_name% my-bucket --role my-role --add-member user:[email protected] --add-member user:test2@email.com
269269
270-
php %command.full_name% my-bucket --role my-role --remove-member user/[email protected]
270+
php %command.full_name% my-bucket --role my-role --remove-member user:[email protected]
271271
272272
EOF
273273
)
274274
->addArgument('bucket', InputArgument::REQUIRED, 'The bucket that you want to change IAM for. ')
275275
->addOption('role', null, InputOption::VALUE_REQUIRED, 'The new role to add to a bucket. ')
276-
->addOption('add-member', null, InputOption::VALUE_REQUIRED, 'The new member to add with the new role to the bucket. ')
276+
->addOption('add-member', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, "The new member(s) to add with the new role to the bucket. ")
277277
->addOption('remove-member', null, InputOption::VALUE_REQUIRED, 'The member to remove from a role for a bucket. ')
278+
->addOption('title', null, InputOption::VALUE_REQUIRED, 'Optional. A title for the condition, if --expression is used. ')
279+
->addOption('description', null, InputOption::VALUE_REQUIRED, 'Optional. A description for the condition, if --expression is used. ')
280+
->addOption('expression', null, InputOption::VALUE_REQUIRED, 'Add the role/members pair with an IAM condition expression. ')
278281
->setCode(function ($input, $output) {
279282
$bucketName = $input->getArgument('bucket');
280283
$role = $input->getOption('role');
281-
$addMember = $input->getOption('add-member');
284+
$members = $input->getOption('add-member');
282285
$removeMember = $input->getOption('remove-member');
283-
if ($addMember) {
286+
$expression = $input->getOption('expression');
287+
$title = $input->getOption('title');
288+
$description = $input->getOption('description');
289+
if ($members) {
284290
if (!$role) {
285291
throw new InvalidArgumentException('Must provide role as an option.');
286292
}
287-
add_bucket_iam_member($bucketName, $role, $addMember);
293+
294+
if ($expression) {
295+
add_bucket_conditional_iam_binding($bucketName, $role, $members, $title, $description, $expression);
296+
} else {
297+
add_bucket_iam_member($bucketName, $role, $members);
298+
}
288299
} elseif ($removeMember) {
289300
if (!$role) {
290301
throw new InvalidArgumentException('Must provide role as an option.');

0 commit comments

Comments
 (0)