From 8d998308ff471f49a293aeda5309895db3a0d6f7 Mon Sep 17 00:00:00 2001 From: Melanie DeJong Date: Tue, 1 Oct 2019 16:42:12 -0700 Subject: [PATCH 1/7] Added test_permissions function and tests for this doc: https://cloud.google.com/iam/docs/testing-permissions --- iam/api-client/access.py | 32 +++++- iam/api-client/access_test.py | 190 ++++++++++++++++++++++++++++------ 2 files changed, 190 insertions(+), 32 deletions(-) diff --git a/iam/api-client/access.py b/iam/api-client/access.py index 337ae80ab7a..15bb9ed67ce 100644 --- a/iam/api-client/access.py +++ b/iam/api-client/access.py @@ -31,7 +31,6 @@ def get_policy(project_id): """Gets IAM policy for a project.""" - # pylint: disable=no-member credentials = service_account.Credentials.from_service_account_file( filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'], scopes=['https://www.googleapis.com/auth/cloud-platform']) @@ -84,7 +83,6 @@ def modify_policy_remove_member(policy, role, member): def set_policy(project_id, policy): """Sets IAM policy for a project.""" - # pylint: disable=no-member credentials = service_account.Credentials.from_service_account_file( filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'], scopes=['https://www.googleapis.com/auth/cloud-platform']) @@ -99,6 +97,29 @@ def set_policy(project_id, policy): return policy # [END iam_set_policy] +# [START iam_test_permissions] +def test_permissions(project_id): + """Tests IAM permissions of the caller""" + + credentials = service_account.Credentials.from_service_account_file( + filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'], + scopes=['https://www.googleapis.com/auth/cloud-platform']) + service = googleapiclient.discovery.build( + 'cloudresourcemanager', 'v1', credentials=credentials) + + permissions = { + "permissions": [ + "resourcemanager.projects.get", + "resourcemanager.projects.delete" + ] + } + + request = service.projects().testIamPermissions(resource=project_id, body=permissions) + returnedPermissions = request.execute() + print(returnedPermissions) + return returnedPermissions +# [END iam_test_permissions] + def main(): parser = argparse.ArgumentParser( @@ -140,6 +161,11 @@ def main(): set_parser.add_argument('project_id') set_parser.add_argument('policy') + # Test permissions + test_permissions_parser = subparsers.add_parser( + 'test_permissions', help=get_policy.__doc__) + test_permissions_parser.add_argument('project_id') + args = parser.parse_args() if args.command == 'get': @@ -152,6 +178,8 @@ def main(): modify_policy_remove_member(args.policy, args.role, args.member) elif args.command == 'add_binding': modify_policy_add_role(args.policy, args.role, args.member) + elif args.command == 'test_permissions': + test_permissions(args.project_id) if __name__ == '__main__': diff --git a/iam/api-client/access_test.py b/iam/api-client/access_test.py index fc73474c87b..9d18e948268 100644 --- a/iam/api-client/access_test.py +++ b/iam/api-client/access_test.py @@ -12,44 +12,174 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Demonstrates how to perform basic access management with Google Cloud IAM. + +For more information, see the documentation at +https://cloud.google.com/iam/docs/granting-changing-revoking-access. +""" + +import argparse import os -import random -import access -import service_accounts +from google.oauth2 import service_account +import googleapiclient.discovery + + +# [START iam_get_policy] +def get_policy(project_id): + """Gets IAM policy for a project.""" + + credentials = service_account.Credentials.from_service_account_file( + filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'], + scopes=['https://www.googleapis.com/auth/cloud-platform']) + service = googleapiclient.discovery.build( + 'cloudresourcemanager', 'v1', credentials=credentials) + policy = service.projects().getIamPolicy( + resource=project_id, body={}).execute() + print(policy) + return policy +# [END iam_get_policy] + + +# [START iam_modify_policy_add_member] +def modify_policy_add_member(policy, role, member): + """Adds a new member to a role binding.""" + + binding = next(b for b in policy['bindings'] if b['role'] == role) + binding['members'].append(member) + print(binding) + return policy +# [END iam_modify_policy_add_member] + + +# [START iam_modify_policy_add_role] +def modify_policy_add_role(policy, role, member): + """Adds a new role binding to a policy.""" + + binding = { + 'role': role, + 'members': [member] + } + policy['bindings'].append(binding) + print(policy) + return policy +# [END iam_modify_policy_add_role] + + +# [START iam_modify_policy_remove_member] +def modify_policy_remove_member(policy, role, member): + """Removes a member from a role binding.""" + binding = next(b for b in policy['bindings'] if b['role'] == role) + if 'members' in binding and member in binding['members']: + binding['members'].remove(member) + print(binding) + return policy +# [END iam_modify_policy_remove_member] + + +# [START iam_set_policy] +def set_policy(project_id, policy): + """Sets IAM policy for a project.""" + + credentials = service_account.Credentials.from_service_account_file( + filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'], + scopes=['https://www.googleapis.com/auth/cloud-platform']) + service = googleapiclient.discovery.build( + 'cloudresourcemanager', 'v1', credentials=credentials) + + policy = service.projects().setIamPolicy( + resource=project_id, body={ + 'policy': policy + }).execute() + print(policy) + return policy +# [END iam_set_policy] + +# [START iam_test_permissions] +def test_permissions(project_id): + """Tests IAM permissions of the caller""" + + credentials = service_account.Credentials.from_service_account_file( + filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'], + scopes=['https://www.googleapis.com/auth/cloud-platform']) + service = googleapiclient.discovery.build( + 'cloudresourcemanager', 'v1', credentials=credentials) + + permissions = { + "permissions": [ + "resourcemanager.projects.get", + "resourcemanager.projects.delete" + ] + } + + request = service.projects().testIamPermissions( + resource=project_id, body=permissions) + returnedPermissions = request.execute() + print(returnedPermissions) + return returnedPermissions +# [END iam_test_permissions] + + +def main(): + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + + subparsers = parser.add_subparsers(dest='command') + + # Get + get_parser = subparsers.add_parser( + 'get', help=get_policy.__doc__) + get_parser.add_argument('project_id') + # Modify: add member + modify_member_parser = subparsers.add_parser( + 'modify_member', help=get_policy.__doc__) + modify_member_parser.add_argument('project_id') + modify_member_parser.add_argument('role') + modify_member_parser.add_argument('member') -def test_access(capsys): - # Setting up variables for testing - project_id = os.environ['GCLOUD_PROJECT'] + # Modify: add role + modify_role_parser = subparsers.add_parser( + 'modify_role', help=get_policy.__doc__) + modify_role_parser.add_argument('project_id') + modify_role_parser.add_argument('project_id') + modify_role_parser.add_argument('role') + modify_role_parser.add_argument('member') - # specifying a sample role to be assigned - gcp_role = 'roles/owner' + # Modify: remove member + modify_member_parser = subparsers.add_parser( + 'modify_member', help=get_policy.__doc__) + modify_member_parser.add_argument('project_id') + modify_member_parser.add_argument('role') + modify_member_parser.add_argument('member') - # section to create service account to test policy updates. - rand = str(random.randint(0, 1000)) - name = 'python-test-' + rand - email = name + '@' + project_id + '.iam.gserviceaccount.com' - member = 'serviceAccount:' + email - service_accounts.create_service_account( - project_id, name, 'Py Test Account') + # Set + set_parser = subparsers.add_parser( + 'set', help=set_policy.__doc__) + set_parser.add_argument('project_id') + set_parser.add_argument('policy') - policy = access.get_policy(project_id) - out, _ = capsys.readouterr() - assert u'etag' in out + # Test permissions + test_permissions_parser = subparsers.add_parser( + 'test_permissions', help=get_policy.__doc__) + test_permissions_parser.add_argument('project_id') - policy = access.modify_policy_add_role(policy, gcp_role, member) - out, _ = capsys.readouterr() - assert u'etag' in out + args = parser.parse_args() - policy = access.modify_policy_remove_member(policy, gcp_role, member) - out, _ = capsys.readouterr() - assert 'iam.gserviceaccount.com' in out + if args.command == 'get': + get_policy(args.project_id) + elif args.command == 'set': + set_policy(args.project_id, args.policy) + elif args.command == 'add_member': + modify_policy_add_member(args.policy, args.role, args.member) + elif args.command == 'remove_member': + modify_policy_remove_member(args.policy, args.role, args.member) + elif args.command == 'add_binding': + modify_policy_add_role(args.policy, args.role, args.member) + elif args.command == 'test_permissions': + test_permissions(args.project_id) - policy = access.set_policy(project_id, policy) - out, _ = capsys.readouterr() - assert u'etag' in out - # deleting the service account created above - service_accounts.delete_service_account( - email) +if __name__ == '__main__': + main() \ No newline at end of file From b52f45591a01fe310f9f95ba5ea991204ef0cef2 Mon Sep 17 00:00:00 2001 From: Melanie DeJong Date: Wed, 2 Oct 2019 09:22:29 -0700 Subject: [PATCH 2/7] Adding access tests Adding back tests that were accidentally removed in a previous commit --- iam/api-client/access_test.py | 192 ++++++---------------------------- 1 file changed, 33 insertions(+), 159 deletions(-) diff --git a/iam/api-client/access_test.py b/iam/api-client/access_test.py index 9d18e948268..313685d125a 100644 --- a/iam/api-client/access_test.py +++ b/iam/api-client/access_test.py @@ -12,174 +12,48 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Demonstrates how to perform basic access management with Google Cloud IAM. - -For more information, see the documentation at -https://cloud.google.com/iam/docs/granting-changing-revoking-access. -""" - -import argparse import os +import random -from google.oauth2 import service_account -import googleapiclient.discovery - - -# [START iam_get_policy] -def get_policy(project_id): - """Gets IAM policy for a project.""" - - credentials = service_account.Credentials.from_service_account_file( - filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'], - scopes=['https://www.googleapis.com/auth/cloud-platform']) - service = googleapiclient.discovery.build( - 'cloudresourcemanager', 'v1', credentials=credentials) - policy = service.projects().getIamPolicy( - resource=project_id, body={}).execute() - print(policy) - return policy -# [END iam_get_policy] - - -# [START iam_modify_policy_add_member] -def modify_policy_add_member(policy, role, member): - """Adds a new member to a role binding.""" - - binding = next(b for b in policy['bindings'] if b['role'] == role) - binding['members'].append(member) - print(binding) - return policy -# [END iam_modify_policy_add_member] - - -# [START iam_modify_policy_add_role] -def modify_policy_add_role(policy, role, member): - """Adds a new role binding to a policy.""" - - binding = { - 'role': role, - 'members': [member] - } - policy['bindings'].append(binding) - print(policy) - return policy -# [END iam_modify_policy_add_role] - - -# [START iam_modify_policy_remove_member] -def modify_policy_remove_member(policy, role, member): - """Removes a member from a role binding.""" - binding = next(b for b in policy['bindings'] if b['role'] == role) - if 'members' in binding and member in binding['members']: - binding['members'].remove(member) - print(binding) - return policy -# [END iam_modify_policy_remove_member] - - -# [START iam_set_policy] -def set_policy(project_id, policy): - """Sets IAM policy for a project.""" - - credentials = service_account.Credentials.from_service_account_file( - filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'], - scopes=['https://www.googleapis.com/auth/cloud-platform']) - service = googleapiclient.discovery.build( - 'cloudresourcemanager', 'v1', credentials=credentials) - - policy = service.projects().setIamPolicy( - resource=project_id, body={ - 'policy': policy - }).execute() - print(policy) - return policy -# [END iam_set_policy] - -# [START iam_test_permissions] -def test_permissions(project_id): - """Tests IAM permissions of the caller""" - - credentials = service_account.Credentials.from_service_account_file( - filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'], - scopes=['https://www.googleapis.com/auth/cloud-platform']) - service = googleapiclient.discovery.build( - 'cloudresourcemanager', 'v1', credentials=credentials) - - permissions = { - "permissions": [ - "resourcemanager.projects.get", - "resourcemanager.projects.delete" - ] - } - - request = service.projects().testIamPermissions( - resource=project_id, body=permissions) - returnedPermissions = request.execute() - print(returnedPermissions) - return returnedPermissions -# [END iam_test_permissions] - - -def main(): - parser = argparse.ArgumentParser( - description=__doc__, - formatter_class=argparse.RawDescriptionHelpFormatter) - - subparsers = parser.add_subparsers(dest='command') +import access +import service_accounts - # Get - get_parser = subparsers.add_parser( - 'get', help=get_policy.__doc__) - get_parser.add_argument('project_id') - # Modify: add member - modify_member_parser = subparsers.add_parser( - 'modify_member', help=get_policy.__doc__) - modify_member_parser.add_argument('project_id') - modify_member_parser.add_argument('role') - modify_member_parser.add_argument('member') +def test_access(capsys): + # Setting up variables for testing + project_id = os.environ['GCLOUD_PROJECT'] - # Modify: add role - modify_role_parser = subparsers.add_parser( - 'modify_role', help=get_policy.__doc__) - modify_role_parser.add_argument('project_id') - modify_role_parser.add_argument('project_id') - modify_role_parser.add_argument('role') - modify_role_parser.add_argument('member') + # specifying a sample role to be assigned + gcp_role = 'roles/owner' - # Modify: remove member - modify_member_parser = subparsers.add_parser( - 'modify_member', help=get_policy.__doc__) - modify_member_parser.add_argument('project_id') - modify_member_parser.add_argument('role') - modify_member_parser.add_argument('member') + # section to create service account to test policy updates. + rand = str(random.randint(0, 1000)) + name = 'python-test-' + rand + email = name + '@' + project_id + '.iam.gserviceaccount.com' + member = 'serviceAccount:' + email + service_accounts.create_service_account( + project_id, name, 'Py Test Account') - # Set - set_parser = subparsers.add_parser( - 'set', help=set_policy.__doc__) - set_parser.add_argument('project_id') - set_parser.add_argument('policy') + policy = access.get_policy(project_id) + out, _ = capsys.readouterr() + assert u'etag' in out - # Test permissions - test_permissions_parser = subparsers.add_parser( - 'test_permissions', help=get_policy.__doc__) - test_permissions_parser.add_argument('project_id') + policy = access.modify_policy_add_role(policy, gcp_role, member) + out, _ = capsys.readouterr() + assert u'etag' in out - args = parser.parse_args() + policy = access.modify_policy_remove_member(policy, gcp_role, member) + out, _ = capsys.readouterr() + assert 'iam.gserviceaccount.com' in out - if args.command == 'get': - get_policy(args.project_id) - elif args.command == 'set': - set_policy(args.project_id, args.policy) - elif args.command == 'add_member': - modify_policy_add_member(args.policy, args.role, args.member) - elif args.command == 'remove_member': - modify_policy_remove_member(args.policy, args.role, args.member) - elif args.command == 'add_binding': - modify_policy_add_role(args.policy, args.role, args.member) - elif args.command == 'test_permissions': - test_permissions(args.project_id) + policy = access.set_policy(project_id, policy) + out, _ = capsys.readouterr() + assert u'etag' in out + access.test_permissions(project_id) + out, _ = capsys.readouterr() + assert u'permissions' in out -if __name__ == '__main__': - main() \ No newline at end of file + # deleting the service account created above + service_accounts.delete_service_account( + email) \ No newline at end of file From a36a24504cdf84c32a4f5979cca5c2df7c504432 Mon Sep 17 00:00:00 2001 From: Melanie DeJong Date: Wed, 2 Oct 2019 09:24:38 -0700 Subject: [PATCH 3/7] Lint --- iam/api-client/access.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/iam/api-client/access.py b/iam/api-client/access.py index 15bb9ed67ce..0a114f0fd64 100644 --- a/iam/api-client/access.py +++ b/iam/api-client/access.py @@ -1,5 +1,3 @@ -# !/usr/bin/env python -# # Copyright 2018 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -98,6 +96,8 @@ def set_policy(project_id, policy): # [END iam_set_policy] # [START iam_test_permissions] + + def test_permissions(project_id): """Tests IAM permissions of the caller""" @@ -109,12 +109,13 @@ def test_permissions(project_id): permissions = { "permissions": [ - "resourcemanager.projects.get", - "resourcemanager.projects.delete" + "resourcemanager.projects.get", + "resourcemanager.projects.delete" ] } - request = service.projects().testIamPermissions(resource=project_id, body=permissions) + request = service.projects().testIamPermissions( + resource=project_id, body=permissions) returnedPermissions = request.execute() print(returnedPermissions) return returnedPermissions @@ -183,4 +184,4 @@ def main(): if __name__ == '__main__': - main() + main() \ No newline at end of file From 8baca115c195247a929cb2ac90d149c20f7bc0db Mon Sep 17 00:00:00 2001 From: Melanie DeJong Date: Wed, 2 Oct 2019 09:32:21 -0700 Subject: [PATCH 4/7] Lint Adding newlines at end of files --- iam/api-client/access.py | 3 ++- iam/api-client/access_test.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/iam/api-client/access.py b/iam/api-client/access.py index 0a114f0fd64..2bf8f1aaeaa 100644 --- a/iam/api-client/access.py +++ b/iam/api-client/access.py @@ -184,4 +184,5 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() + \ No newline at end of file diff --git a/iam/api-client/access_test.py b/iam/api-client/access_test.py index 313685d125a..b98e1d22aec 100644 --- a/iam/api-client/access_test.py +++ b/iam/api-client/access_test.py @@ -56,4 +56,5 @@ def test_access(capsys): # deleting the service account created above service_accounts.delete_service_account( - email) \ No newline at end of file + email) + \ No newline at end of file From de6433da33155a96fe9b9f4cd57f4404e439f903 Mon Sep 17 00:00:00 2001 From: melaniedejong <35782177+melaniedejong@users.noreply.github.com> Date: Wed, 2 Oct 2019 09:53:24 -0700 Subject: [PATCH 5/7] Lint --- iam/api-client/access.py | 1 - 1 file changed, 1 deletion(-) diff --git a/iam/api-client/access.py b/iam/api-client/access.py index 2bf8f1aaeaa..9dcca7fa6f3 100644 --- a/iam/api-client/access.py +++ b/iam/api-client/access.py @@ -185,4 +185,3 @@ def main(): if __name__ == '__main__': main() - \ No newline at end of file From 7056e0915f2694ef864b5622426f7c3fcc24cd3e Mon Sep 17 00:00:00 2001 From: melaniedejong <35782177+melaniedejong@users.noreply.github.com> Date: Wed, 2 Oct 2019 10:12:37 -0700 Subject: [PATCH 6/7] Lint --- iam/api-client/access_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/iam/api-client/access_test.py b/iam/api-client/access_test.py index b98e1d22aec..360393c83bc 100644 --- a/iam/api-client/access_test.py +++ b/iam/api-client/access_test.py @@ -57,4 +57,3 @@ def test_access(capsys): # deleting the service account created above service_accounts.delete_service_account( email) - \ No newline at end of file From 4cf6a02f6e04039fd4152a472db0059d62b683a2 Mon Sep 17 00:00:00 2001 From: melaniedejong <35782177+melaniedejong@users.noreply.github.com> Date: Wed, 23 Oct 2019 13:43:22 -0700 Subject: [PATCH 7/7] Fix spacing --- iam/api-client/access.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iam/api-client/access.py b/iam/api-client/access.py index 9dcca7fa6f3..de228e8b6cc 100644 --- a/iam/api-client/access.py +++ b/iam/api-client/access.py @@ -95,9 +95,8 @@ def set_policy(project_id, policy): return policy # [END iam_set_policy] -# [START iam_test_permissions] - +# [START iam_test_permissions] def test_permissions(project_id): """Tests IAM permissions of the caller"""