diff --git a/.gitignore b/.gitignore index b05a386dfb4..79fbc1fc767 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,4 @@ credentials.dat .nox .vscode/ *sponge_log.xml -.DS_store \ No newline at end of file +.DS_store diff --git a/iam/api-client/grantable_roles.py b/iam/api-client/grantable_roles.py new file mode 100644 index 00000000000..e5986e7e1e7 --- /dev/null +++ b/iam/api-client/grantable_roles.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +# Copyright 2018 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import os + +from google.oauth2 import service_account +import googleapiclient.discovery + +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( + 'iam', 'v1', credentials=credentials) + + +# [START iam_view_grantable_roles] +def view_grantable_roles(full_resource_name): + roles = service.roles().queryGrantableRoles(body={ + 'fullResourceName': full_resource_name + }).execute() + + for role in roles['roles']: + print('Title: ' + role['title']) + print('Name: ' + role['name']) + print('Description: ' + role['description']) + print(' ') +# [END iam_view_grantable_roles] + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + 'full_resource_name', + help='The full name of the resource to query grantable roles for.') + + args = parser.parse_args() + view_grantable_roles(args.full_resource_name) diff --git a/iam/api-client/grantable_roles_test.py b/iam/api-client/grantable_roles_test.py new file mode 100644 index 00000000000..87af3564b93 --- /dev/null +++ b/iam/api-client/grantable_roles_test.py @@ -0,0 +1,25 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +import grantable_roles + + +def test_service_accounts(capsys): + project = os.environ['GCLOUD_PROJECT'] + resource = '//cloudresourcemanager.googleapis.com/projects/' + project + grantable_roles.view_grantable_roles(resource) + out, _ = capsys.readouterr() + assert 'Title:' in out diff --git a/iam/api-client/quickstart.py b/iam/api-client/quickstart.py new file mode 100644 index 00000000000..932e6832010 --- /dev/null +++ b/iam/api-client/quickstart.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python + +# Copyright 2018 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def quickstart(): + # [START iam_quickstart] + import os + + from google.oauth2 import service_account + import googleapiclient.discovery + + # Get credentials + credentials = service_account.Credentials.from_service_account_file( + filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'], + scopes=['https://www.googleapis.com/auth/cloud-platform']) + + # Create the Cloud IAM service object + service = googleapiclient.discovery.build( + 'iam', 'v1', credentials=credentials) + + # Call the Cloud IAM Roles API + # If using pylint, disable weak-typing warnings + # pylint: disable=no-member + response = service.roles().list().execute() + roles = response['roles'] + + # Process the response + for role in roles: + print('Title: ' + role['title']) + print('Name: ' + role['name']) + print('Description: ' + role['description']) + print('') + # [END iam_quickstart] + + +if __name__ == '__main__': + quickstart() diff --git a/iam/api-client/quickstart_test.py b/iam/api-client/quickstart_test.py new file mode 100644 index 00000000000..9c7d881a6bc --- /dev/null +++ b/iam/api-client/quickstart_test.py @@ -0,0 +1,21 @@ +# Copyright 2018 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import quickstart + + +def test_quickstart(capsys): + quickstart.quickstart() + out, _ = capsys.readouterr() + assert 'Title' in out diff --git a/iam/api-client/requirements.txt b/iam/api-client/requirements.txt new file mode 100644 index 00000000000..73d5bf5c6df --- /dev/null +++ b/iam/api-client/requirements.txt @@ -0,0 +1,3 @@ +google-api-python-client==1.7.3 +google-auth==1.5.0 +google-auth-httplib2==0.0.3 \ No newline at end of file diff --git a/iam/api-client/service_account_keys.py b/iam/api-client/service_account_keys.py new file mode 100644 index 00000000000..b73227dd794 --- /dev/null +++ b/iam/api-client/service_account_keys.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python + +# Copyright 2018 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Demonstrates how to perform basic operations with Google Cloud IAM +service account keys. + +For more information, see the documentation at +https://cloud.google.com/iam/docs/creating-managing-service-account-keys. +""" + +import argparse +import os + +from google.oauth2 import service_account +import googleapiclient.discovery + +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( + 'iam', 'v1', credentials=credentials) + + +# [START iam_create_key] +def create_key(service_account_email): + """Creates a key for a service account.""" + + # pylint: disable=no-member + key = service.projects().serviceAccounts().keys().create( + name='projects/-/serviceAccounts/' + service_account_email, body={} + ).execute() + + print('Created key: ' + key['name']) +# [END iam_create_key] + + +# [START iam_list_keys] +def list_keys(service_account_email): + """Lists all keys for a service account.""" + + # pylint: disable=no-member + keys = service.projects().serviceAccounts().keys().list( + name='projects/-/serviceAccounts/' + service_account_email).execute() + + for key in keys['keys']: + print('Key: ' + key['name']) +# [END iam_list_keys] + + +# [START iam_delete_key] +def delete_key(full_key_name): + """Deletes a service account key.""" + + # pylint: disable=no-member + service.projects().serviceAccounts().keys().delete( + name=full_key_name).execute() + + print('Deleted key: ' + full_key_name) +# [END iam_delete_key] + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + + subparsers = parser.add_subparsers(dest='command') + + create_key_parser = subparsers.add_parser( + 'create', help=create_key.__doc__) + create_key_parser.add_argument('service_account_email') + + list_keys_parser = subparsers.add_parser( + 'list', help=list_keys.__doc__) + list_keys_parser.add_argument('service_account_email') + + delete_key_parser = subparsers.add_parser( + 'delete', help=delete_key.__doc__) + delete_key_parser.add_argument('full_key_name') + + args = parser.parse_args() + + if args.command == 'list': + list_keys(args.service_account_email) + elif args.command == 'create': + create_key(args.service_account_email) + elif args.command == 'delete': + delete_key(args.full_key_name) diff --git a/iam/api-client/service_accounts.py b/iam/api-client/service_accounts.py new file mode 100644 index 00000000000..f70e6024b2d --- /dev/null +++ b/iam/api-client/service_accounts.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python + +# Copyright 2018 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Demonstrates how to perform basic operations with Google Cloud IAM +service accounts. +For more information, see the documentation at +https://cloud.google.com/iam/docs/creating-managing-service-accounts. +""" + +import argparse +import os + +from google.oauth2 import service_account +import googleapiclient.discovery + +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( + 'iam', 'v1', credentials=credentials) + + +# [START iam_create_service_account] +def create_service_account(project_id, name, display_name): + """Creates a service account.""" + + # pylint: disable=no-member + service_account = service.projects().serviceAccounts().create( + name='projects/' + project_id, + body={ + 'accountId': name, + 'serviceAccount': { + 'displayName': display_name + } + }).execute() + + print('Created service account: ' + service_account['email']) + return service_account +# [END iam_create_service_account] + + +# [START iam_list_service_accounts] +def list_service_accounts(project_id): + """Lists all service accounts for the current project.""" + + # pylint: disable=no-member + service_accounts = service.projects().serviceAccounts().list( + name='projects/' + project_id).execute() + + for account in service_accounts['accounts']: + print('Name: ' + account['name']) + print('Email: ' + account['email']) + print(' ') + return service_accounts +# [END iam_list_service_accounts] + + +# [START iam_rename_service_account] +def rename_service_account(email, new_display_name): + """Changes a service account's display name.""" + + # First, get a service account using List() or Get() + resource = 'projects/-/serviceAccounts/' + email + # pylint: disable=no-member + service_account = service.projects().serviceAccounts().get( + name=resource).execute() + + # Then you can update the display name + service_account['displayName'] = new_display_name + service_account = service.projects().serviceAccounts().update( + name=resource, body=service_account).execute() + + print('Updated display name for {} to: {}'.format( + service_account['email'], service_account['displayName'])) + return service_account +# [END iam_rename_service_account] + + +# [START iam_delete_service_account] +def delete_service_account(email): + """Deletes a service account.""" + + # pylint: disable=no-member + service.projects().serviceAccounts().delete( + name='projects/-/serviceAccounts/' + email).execute() + + print('Deleted service account: ' + email) +# [END iam_delete_service_account] + + +def main(): + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + + subparsers = parser.add_subparsers(dest='command') + + # Create + create_parser = subparsers.add_parser( + 'create', help=create_service_account.__doc__) + create_parser.add_argument('project_id') + create_parser.add_argument('name') + create_parser.add_argument('display_name') + + # List + list_parser = subparsers.add_parser( + 'list', help=list_service_accounts.__doc__) + list_parser.add_argument('project_id') + + # Rename + rename_parser = subparsers.add_parser( + 'delete', help=rename_service_account.__doc__) + rename_parser.add_argument('email') + rename_parser.add_argument('new_display_name') + + # Delete + delete_parser = subparsers.add_parser( + 'delete', help=delete_service_account.__doc__) + delete_parser.add_argument('email') + + args = parser.parse_args() + + if args.command == 'create': + create_service_account(args.project_id, args.name, args.display_name) + elif args.command == 'list': + list_service_accounts(args.project_id) + elif args.command == 'rename': + rename_service_account(args.email, args.new_display_name) + elif args.command == 'delete': + delete_service_account(args.email) + + +if __name__ == '__main__': + main() diff --git a/iam/api-client/service_accounts_test.py b/iam/api-client/service_accounts_test.py new file mode 100644 index 00000000000..d96123a5f14 --- /dev/null +++ b/iam/api-client/service_accounts_test.py @@ -0,0 +1,34 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import random + +import service_accounts + + +def test_service_accounts(capsys): + project_id = os.environ['GCLOUD_PROJECT'] + rand = str(random.randint(0, 1000)) + name = 'python-test-' + rand + email = name + '@' + project_id + '.iam.gserviceaccount.com' + + service_accounts.create_service_account( + project_id, name, 'Py Test Account') + service_accounts.list_service_accounts( + project_id) + service_accounts.rename_service_account( + email, 'Updated Py Test Account') + service_accounts.delete_service_account( + email)