diff --git a/samples/snippets/README.rst b/samples/snippets/README.rst index 865cab4..af98fb3 100644 --- a/samples/snippets/README.rst +++ b/samples/snippets/README.rst @@ -280,6 +280,64 @@ To run this sample: +IAM Grant Access ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. image:: https://gstatic.com/cloudssh/images/open-btn.png + :target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=secretmanager/api-client/iam_grant_access.py,secretmanager/api-client/README.rst + + + + +To run this sample: + +.. code-block:: bash + + $ python iam_grant_access.py + + usage: iam_grant_access.py [-h] project_id secret_id member + + command line application and sample code for granting access to a secret. + + positional arguments: + project_id id of the GCP project + secret_id id of the secret to get + member member to grant access + + optional arguments: + -h, --help show this help message and exit + + + +IAM Revoke Access ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. image:: https://gstatic.com/cloudssh/images/open-btn.png + :target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=secretmanager/api-client/iam_revoke_access.py,secretmanager/api-client/README.rst + + + + +To run this sample: + +.. code-block:: bash + + $ python iam_revoke_access.py + + usage: iam_revoke_access.py [-h] project_id secret_id member + + command line application and sample code for revoking access to a secret. + + positional arguments: + project_id id of the GCP project + secret_id id of the secret to get + member member to revoke access + + optional arguments: + -h, --help show this help message and exit + + + Get Secret +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/samples/snippets/README.rst.in b/samples/snippets/README.rst.in index 0671857..ddd46a4 100644 --- a/samples/snippets/README.rst.in +++ b/samples/snippets/README.rst.in @@ -36,6 +36,12 @@ samples: - name: Get Secret Version file: get_secret_version.py show_help: True +- name: IAM Grant Access + file: iam_grant_access.py + show_help: True +- name: IAM Revoke Access + file: iam_revoke_access.py + show_help: True - name: Get Secret file: get_secret.py show_help: True diff --git a/samples/snippets/iam_grant_access.py b/samples/snippets/iam_grant_access.py new file mode 100644 index 0000000..1454d6d --- /dev/null +++ b/samples/snippets/iam_grant_access.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +# Copyright 2020 Google LLC +# +# 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 +""" +command line application and sample code for granting access to a secret. +""" + +import argparse + + +# [START secretmanager_iam_grant_access] +def iam_grant_access(project_id, secret_id, member): + """ + Grant the given member access to a secret. + """ + + # Import the Secret Manager client library. + from google.cloud import secretmanager_v1beta1 as secretmanager + + # Create the Secret Manager client. + client = secretmanager.SecretManagerServiceClient() + + # Build the resource name of the secret. + name = client.secret_path(project_id, secret_id) + + # Get the current IAM policy. + policy = client.get_iam_policy(name) + + # Add the given member with access permissions. + policy.bindings.add( + role='roles/secretmanager.secretAccessor', + members=[member]) + + # Update the IAM Policy. + new_policy = client.set_iam_policy(name, policy) + + # Print data about the secret. + print('Updated IAM policy on {}'.format(secret_id)) +# [END secretmanager_iam_grant_access] + + return new_policy + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('project_id', help='id of the GCP project') + parser.add_argument('secret_id', help='id of the secret to get') + parser.add_argument('member', help='member to grant access') + args = parser.parse_args() + + iam_grant_access(args.project_id, args.secret_id, args.member) diff --git a/samples/snippets/iam_revoke_access.py b/samples/snippets/iam_revoke_access.py new file mode 100644 index 0000000..5eb7fc0 --- /dev/null +++ b/samples/snippets/iam_revoke_access.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +# Copyright 2020 Google LLC +# +# 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 +""" +command line application and sample code for revoking access to a secret. +""" + +import argparse + + +# [START secretmanager_iam_revoke_access] +def iam_revoke_access(project_id, secret_id, member): + """ + Revoke the given member access to a secret. + """ + + # Import the Secret Manager client library. + from google.cloud import secretmanager_v1beta1 as secretmanager + + # Create the Secret Manager client. + client = secretmanager.SecretManagerServiceClient() + + # Build the resource name of the secret. + name = client.secret_path(project_id, secret_id) + + # Get the current IAM policy. + policy = client.get_iam_policy(name) + + # Remove the given member's access permissions. + accessRole = 'roles/secretmanager.secretAccessor' + for b in list(policy.bindings): + if b.role == accessRole and member in b.members: + b.members.remove(member) + + # Update the IAM Policy. + new_policy = client.set_iam_policy(name, policy) + + # Print data about the secret. + print('Updated IAM policy on {}'.format(secret_id)) +# [END secretmanager_iam_revoke_access] + + return new_policy + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('project_id', help='id of the GCP project') + parser.add_argument('secret_id', help='id of the secret to get') + parser.add_argument('member', help='member to revoke access') + args = parser.parse_args() + + iam_revoke_access(args.project_id, args.secret_id, args.member) diff --git a/samples/snippets/snippets_test.py b/samples/snippets/snippets_test.py index 6269286..18f3634 100644 --- a/samples/snippets/snippets_test.py +++ b/samples/snippets/snippets_test.py @@ -23,8 +23,10 @@ from destroy_secret_version import destroy_secret_version from disable_secret_version import disable_secret_version from enable_secret_version import enable_secret_version -from get_secret_version import get_secret_version from get_secret import get_secret +from get_secret_version import get_secret_version +from iam_grant_access import iam_grant_access +from iam_revoke_access import iam_revoke_access from list_secret_versions import list_secret_versions from list_secrets import list_secrets from update_secret import update_secret @@ -43,6 +45,11 @@ def project_id(): return os.environ['GCLOUD_PROJECT'] +@pytest.fixture() +def iam_user(): + return 'serviceAccount:' + os.environ['GCLOUD_SECRETS_SERVICE_ACCOUNT'] + + @pytest.fixture() def secret(client, project_id): parent = client.project_path(project_id) @@ -145,6 +152,18 @@ def test_get_secret(client, secret): assert secret_id in snippet_secret.name +def test_iam_grant_access(client, secret, iam_user): + project_id, secret_id = secret + policy = iam_grant_access(project_id, secret_id, iam_user) + assert any(iam_user in b.members for b in policy.bindings) + + +def test_iam_revoke_access(client, secret, iam_user): + project_id, secret_id = secret + policy = iam_revoke_access(project_id, secret_id, iam_user) + assert not any(iam_user in b.members for b in policy.bindings) + + def test_list_secret_versions(capsys, secret_version, another_secret_version): project_id, secret_id, version_id = secret_version _, _, another_version_id = another_secret_version