diff --git a/.kokoro/continuous/iam.cfg b/.kokoro/continuous/iam.cfg new file mode 100644 index 000000000000..812d891c07f8 --- /dev/null +++ b/.kokoro/continuous/iam.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Tell the trampoline which build file to use. +env_vars: { + key: "PACKAGE" + value: "iam" +} diff --git a/.kokoro/presubmit/iam.cfg b/.kokoro/presubmit/iam.cfg new file mode 100644 index 000000000000..812d891c07f8 --- /dev/null +++ b/.kokoro/presubmit/iam.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Tell the trampoline which build file to use. +env_vars: { + key: "PACKAGE" + value: "iam" +} diff --git a/.kokoro/release/iam.cfg b/.kokoro/release/iam.cfg new file mode 100644 index 000000000000..812d891c07f8 --- /dev/null +++ b/.kokoro/release/iam.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Tell the trampoline which build file to use. +env_vars: { + key: "PACKAGE" + value: "iam" +} diff --git a/docs/iam b/docs/iam new file mode 120000 index 000000000000..783f393b393c --- /dev/null +++ b/docs/iam @@ -0,0 +1 @@ +../iam/docs \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index af95fd015e3e..8b4627e812ee 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -14,6 +14,7 @@ Data Loss Prevention DNS Firestore + IAM IoT Key Management Language diff --git a/docs/requirements.txt b/docs/requirements.txt index 072b7e291a07..1ff3f9b48848 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -18,6 +18,7 @@ grpcio-gcp >= 0.2.2 -e dlp/ -e dns/ -e firestore/ +-e iam/ -e iot/ -e kms/ -e language/ diff --git a/iam/.coveragerc b/iam/.coveragerc new file mode 100644 index 000000000000..6b9ab9da4a1b --- /dev/null +++ b/iam/.coveragerc @@ -0,0 +1,18 @@ +[run] +branch = True + +[report] +fail_under = 100 +show_missing = True +exclude_lines = + # Re-enable the standard pragma + pragma: NO COVER + # Ignore debug-only repr + def __repr__ + # Ignore abstract methods + raise NotImplementedError +omit = + */gapic/*.py + */proto/*.py + */core/*.py + */site-packages/*.py \ No newline at end of file diff --git a/iam/.flake8 b/iam/.flake8 new file mode 100644 index 000000000000..61766fa84d02 --- /dev/null +++ b/iam/.flake8 @@ -0,0 +1,13 @@ +[flake8] +ignore = E203, E266, E501, W503 +exclude = + # Exclude generated code. + **/proto/** + **/gapic/** + *_pb2.py + + # Standard linting exemptions. + __pycache__, + .git, + *.pyc, + conf.py diff --git a/iam/LICENSE b/iam/LICENSE new file mode 100644 index 000000000000..a8ee855de2aa --- /dev/null +++ b/iam/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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 + + https://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. diff --git a/iam/MANIFEST.in b/iam/MANIFEST.in new file mode 100644 index 000000000000..9cbf175afe6b --- /dev/null +++ b/iam/MANIFEST.in @@ -0,0 +1,5 @@ +include README.rst LICENSE +recursive-include google *.json *.proto +recursive-include tests * +global-exclude *.py[co] +global-exclude __pycache__ diff --git a/iam/README.rst b/iam/README.rst new file mode 100644 index 000000000000..d77703962802 --- /dev/null +++ b/iam/README.rst @@ -0,0 +1,83 @@ +Python Client for IAM API (`Alpha`_) +================================================================ + +`IAM Service Account Credentials API`_: IAM Service Account Credentials API + +- `Client Library Documentation`_ +- `Product Documentation`_ + +.. _Alpha: https://github.com/googleapis/google-cloud-python/blob/master/README.rst +.. _IAM API: https://cloud.google.com/iam +.. _Client Library Documentation: https://googleapis.github.io/google-cloud-python/latest/iam/usage.html +.. _Product Documentation: https://cloud.google.com/iam + +Quick Start +----------- + +In order to use this library, you first need to go through the following steps: + +1. `Select or create a Cloud Platform project.`_ +2. `Enable billing for your project.`_ +3. `Enable the IAM Service Account Credentials API.`_ +4. `Setup Authentication.`_ + +.. _Select or create a Cloud Platform project.: https://console.cloud.google.com/project +.. _Enable billing for your project.: https://cloud.google.com/billing/docs/how-to/modify-project#enable_billing_for_a_project +.. _Enable the IAM Service Account Credentials API.: https://cloud.google.com/iam +.. _Setup Authentication.: https://googleapis.github.io/google-cloud-python/latest/core/auth.html + +Installation +~~~~~~~~~~~~ + +Install this library in a `virtualenv`_ using pip. `virtualenv`_ is a tool to +create isolated Python environments. The basic problem it addresses is one of +dependencies and versions, and indirectly permissions. + +With `virtualenv`_, it's possible to install this library without needing system +install permissions, and without clashing with the installed system +dependencies. + +.. _`virtualenv`: https://virtualenv.pypa.io/en/latest/ + +Supported Python Versions +^^^^^^^^^^^^^^^^^^^^^^^^^ +Python >= 3.4 + +Deprecated Python Versions +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Python == 2.7. Python 2.7 support will be removed on January 1, 2020. + + +Mac/Linux +^^^^^^^^^ + +.. code-block:: console + + pip install virtualenv + virtualenv + source /bin/activate + /bin/pip install google-cloud-iam + + +Windows +^^^^^^^ + +.. code-block:: console + + pip install virtualenv + virtualenv + \Scripts\activate + \Scripts\pip.exe install google-cloud-iam + +Next Steps +~~~~~~~~~~ + +- Read the `Client Library Documentation`_ for IAM API + API to see other available methods on the client. +- Read the `IAM API Product documentation`_ to learn + more about the product and see How-to Guides. +- View this `repository’s main README`_ to see the full list of Cloud + APIs that we cover. + +.. _IAM API Product documentation: https://cloud.google.com/iam +.. _repository’s main README: https://github.com/googleapis/google-cloud-python/blob/master/README.rst \ No newline at end of file diff --git a/iam/docs/conf.py b/iam/docs/conf.py new file mode 100644 index 000000000000..32fa3aadb492 --- /dev/null +++ b/iam/docs/conf.py @@ -0,0 +1,319 @@ +# -*- coding: utf-8 -*- +# +# google-cloud-iam documentation build configuration file +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import shlex + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath("..")) + +__version__ = "0.1.0" + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.intersphinx", + "sphinx.ext.coverage", + "sphinx.ext.napoleon", + "sphinx.ext.viewcode", +] + +# autodoc/autosummary flags +autoclass_content = "both" +autodoc_default_flags = ["members"] +autosummary_generate = True + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = ".rst" + +# The encoding of source files. +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = "index" + +# General information about the project. +project = u"google-cloud-iam" +copyright = u"2017, Google" +author = u"Google APIs" + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The full version, including alpha/beta/rc tags. +release = __version__ +# The short X.Y version. +version = ".".join(release.split(".")[0:2]) + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# today = '' +# Else, today_fmt is used as the format for a strftime call. +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ["_build"] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +# default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +# add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +# add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "sphinx" + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +# keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = "sphinx_rtd_theme" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +# html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +# html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +# html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +# html_static_path = [] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +# html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +# html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +# html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# html_additional_pages = {} + +# If false, no module index is generated. +# html_domain_indices = True + +# If false, no index is generated. +# html_use_index = True + +# If true, the index is split into individual pages for each letter. +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +# html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +# html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +# html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +# html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = "google-cloud-iam-doc" + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', + # Latex figure (float) alignment + #'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ( + master_doc, + "google-cloud-iam.tex", + u"google-cloud-iam Documentation", + author, + "manual", + ) +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# latex_use_parts = False + +# If true, show page references after internal links. +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# latex_appendices = [] + +# If false, no module index is generated. +# latex_domain_indices = True + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, "google-cloud-iam", u"google-cloud-iam Documentation", [author], 1) +] + +# If true, show URL addresses after external links. +# man_show_urls = False + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ( + master_doc, + "google-cloud-iam", + u"google-cloud-iam Documentation", + author, + "google-cloud-iam", + "GAPIC library for the {metadata.shortName} v1 service", + "APIs", + ) +] + +# Documents to append as an appendix to all manuals. +# texinfo_appendices = [] + +# If false, no module index is generated. +# texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +# texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +# texinfo_no_detailmenu = False + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = { + "python": ("http://python.readthedocs.org/en/latest/", None), + "gax": ("https://gax-python.readthedocs.org/en/latest/", None), +} + +# Napoleon settings +napoleon_google_docstring = True +napoleon_numpy_docstring = True +napoleon_include_private_with_doc = False +napoleon_include_special_with_doc = True +napoleon_use_admonition_for_examples = False +napoleon_use_admonition_for_notes = False +napoleon_use_admonition_for_references = False +napoleon_use_ivar = False +napoleon_use_param = True +napoleon_use_rtype = True diff --git a/iam/docs/gapic/v1/api.rst b/iam/docs/gapic/v1/api.rst new file mode 100644 index 000000000000..898390081ea9 --- /dev/null +++ b/iam/docs/gapic/v1/api.rst @@ -0,0 +1,6 @@ +Client for IAM Service Account Credentials API +============================================== + +.. automodule:: google.cloud.iam_credentials_v1 + :members: + :inherited-members: \ No newline at end of file diff --git a/iam/docs/gapic/v1/types.rst b/iam/docs/gapic/v1/types.rst new file mode 100644 index 000000000000..a80cc353174d --- /dev/null +++ b/iam/docs/gapic/v1/types.rst @@ -0,0 +1,5 @@ +Types for IAM Service Account Credentials API Client +==================================================== + +.. automodule:: google.cloud.iam_credentials_v1.types + :members: \ No newline at end of file diff --git a/iam/docs/index.rst b/iam/docs/index.rst new file mode 100644 index 000000000000..cc33f3619283 --- /dev/null +++ b/iam/docs/index.rst @@ -0,0 +1,9 @@ +.. include:: /../iam/README.rst + +API Reference +------------- +.. toctree:: + :maxdepth: 2 + + gapic/v1/api + gapic/v1/types \ No newline at end of file diff --git a/iam/google/__init__.py b/iam/google/__init__.py new file mode 100644 index 000000000000..7aa71bb4e2f1 --- /dev/null +++ b/iam/google/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2018 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 +# +# https://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. + +try: + import pkg_resources + + pkg_resources.declare_namespace(__name__) +except ImportError: + import pkgutil + + __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/iam/google/cloud/__init__.py b/iam/google/cloud/__init__.py new file mode 100644 index 000000000000..7aa71bb4e2f1 --- /dev/null +++ b/iam/google/cloud/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2018 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 +# +# https://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. + +try: + import pkg_resources + + pkg_resources.declare_namespace(__name__) +except ImportError: + import pkgutil + + __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/iam/google/cloud/iam_credentials.py b/iam/google/cloud/iam_credentials.py new file mode 100644 index 000000000000..cc9540790f81 --- /dev/null +++ b/iam/google/cloud/iam_credentials.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2018 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 +# +# https://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. + +from __future__ import absolute_import + +from google.cloud.iam_credentials_v1 import IAMCredentialsClient +from google.cloud.iam_credentials_v1 import types + +__all__ = ("types", "IAMCredentialsClient") diff --git a/iam/google/cloud/iam_credentials_v1/__init__.py b/iam/google/cloud/iam_credentials_v1/__init__.py new file mode 100644 index 000000000000..2714c235b8f7 --- /dev/null +++ b/iam/google/cloud/iam_credentials_v1/__init__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2018 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 +# +# https://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. + +from __future__ import absolute_import + +from google.cloud.iam_credentials_v1 import types +from google.cloud.iam_credentials_v1.gapic import iam_credentials_client + + +class IAMCredentialsClient(iam_credentials_client.IAMCredentialsClient): + __doc__ = iam_credentials_client.IAMCredentialsClient.__doc__ + + +__all__ = ("types", "IAMCredentialsClient") diff --git a/iam/google/cloud/iam_credentials_v1/gapic/__init__.py b/iam/google/cloud/iam_credentials_v1/gapic/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client.py b/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client.py new file mode 100644 index 000000000000..b5ed9a5eae3f --- /dev/null +++ b/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client.py @@ -0,0 +1,504 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2018 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 +# +# https://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. +"""Accesses the google.iam.credentials.v1 IAMCredentials API.""" + +import pkg_resources +import warnings + +from google.oauth2 import service_account +import google.api_core.gapic_v1.client_info +import google.api_core.gapic_v1.config +import google.api_core.gapic_v1.method +import google.api_core.grpc_helpers +import google.api_core.path_template +import grpc + +from google.cloud.iam_credentials_v1.gapic import iam_credentials_client_config +from google.cloud.iam_credentials_v1.gapic.transports import ( + iam_credentials_grpc_transport, +) +from google.cloud.iam_credentials_v1.proto import common_pb2 +from google.cloud.iam_credentials_v1.proto import iamcredentials_pb2_grpc +from google.protobuf import duration_pb2 + +_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution("google-cloud-iam").version + + +class IAMCredentialsClient(object): + """ + A service account is a special type of Google account that belongs to your + application or a virtual machine (VM), instead of to an individual end user. + Your application assumes the identity of the service account to call Google + APIs, so that the users aren't directly involved. + + Service account credentials are used to temporarily assume the identity + of the service account. Supported credential types include OAuth 2.0 access + tokens, OpenID Connect ID tokens, self-signed JSON Web Tokens (JWTs), and + more. + """ + + SERVICE_ADDRESS = "iamcredentials.googleapis.com:443" + """The default address of the service.""" + + # The name of the interface for this client. This is the key used to + # find the method configuration in the client_config dictionary. + _INTERFACE_NAME = "google.iam.credentials.v1.IAMCredentials" + + @classmethod + def from_service_account_file(cls, filename, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + IAMCredentialsClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file(filename) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + @classmethod + def service_account_path(cls, project, service_account): + """Return a fully-qualified service_account string.""" + return google.api_core.path_template.expand( + "projects/{project}/serviceAccounts/{service_account}", + project=project, + service_account=service_account, + ) + + def __init__( + self, + transport=None, + channel=None, + credentials=None, + client_config=None, + client_info=None, + ): + """Constructor. + + Args: + transport (Union[~.IamCredentialsGrpcTransport, + Callable[[~.Credentials, type], ~.IamCredentialsGrpcTransport]): A transport + instance, responsible for actually making the API calls. + The default transport uses the gRPC protocol. + This argument may also be a callable which returns a + transport instance. Callables will be sent the credentials + as the first argument and the default transport class as + the second argument. + channel (grpc.Channel): DEPRECATED. A ``Channel`` instance + through which to make calls. This argument is mutually exclusive + with ``credentials``; providing both will raise an exception. + credentials (google.auth.credentials.Credentials): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is mutually exclusive with providing a + transport instance to ``transport``; doing so will raise + an exception. + client_config (dict): DEPRECATED. A dictionary of call options for + each method. If not specified, the default configuration is used. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + """ + # Raise deprecation warnings for things we want to go away. + if client_config is not None: + warnings.warn( + "The `client_config` argument is deprecated.", + PendingDeprecationWarning, + stacklevel=2, + ) + else: + client_config = iam_credentials_client_config.config + + if channel: + warnings.warn( + "The `channel` argument is deprecated; use " "`transport` instead.", + PendingDeprecationWarning, + stacklevel=2, + ) + + # Instantiate the transport. + # The transport is responsible for handling serialization and + # deserialization and actually sending data to the service. + if transport: + if callable(transport): + self.transport = transport( + credentials=credentials, + default_class=iam_credentials_grpc_transport.IamCredentialsGrpcTransport, + ) + else: + if credentials: + raise ValueError( + "Received both a transport instance and " + "credentials; these are mutually exclusive." + ) + self.transport = transport + else: + self.transport = iam_credentials_grpc_transport.IamCredentialsGrpcTransport( + address=self.SERVICE_ADDRESS, channel=channel, credentials=credentials + ) + + if client_info is None: + client_info = google.api_core.gapic_v1.client_info.ClientInfo( + gapic_version=_GAPIC_LIBRARY_VERSION + ) + else: + client_info.gapic_version = _GAPIC_LIBRARY_VERSION + self._client_info = client_info + + # Parse out the default settings for retry and timeout for each RPC + # from the client configuration. + # (Ordinarily, these are the defaults specified in the `*_config.py` + # file next to this one.) + self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( + client_config["interfaces"][self._INTERFACE_NAME] + ) + + # Save a dictionary of cached API call functions. + # These are the actual callables which invoke the proper + # transport methods, wrapped with `wrap_method` to add retry, + # timeout, and the like. + self._inner_api_calls = {} + + # Service calls + def generate_access_token( + self, + name, + scope, + delegates=None, + lifetime=None, + retry=google.api_core.gapic_v1.method.DEFAULT, + timeout=google.api_core.gapic_v1.method.DEFAULT, + metadata=None, + ): + """ + Generates an OAuth 2.0 access token for a service account. + + Example: + >>> from google.cloud import iam_credentials_v1 + >>> + >>> client = iam_credentials_v1.IAMCredentialsClient() + >>> + >>> name = client.service_account_path('[PROJECT]', '[SERVICE_ACCOUNT]') + >>> + >>> # TODO: Initialize `scope`: + >>> scope = [] + >>> + >>> response = client.generate_access_token(name, scope) + + Args: + name (str): The resource name of the service account for which the credentials are + requested, in the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. + scope (list[str]): Code to identify the scopes to be included in the OAuth 2.0 access token. + See https://developers.google.com/identity/protocols/googlescopes for more + information. + At least one value required. + delegates (list[str]): The sequence of service accounts in a delegation chain. Each service + account must be granted the ``roles/iam.serviceAccountTokenCreator`` + role on its next service account in the chain. The last service account + in the chain must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on the service account + that is specified in the ``name`` field of the request. + + The delegates must have the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`` + lifetime (Union[dict, ~google.cloud.iam_credentials_v1.types.Duration]): The desired lifetime duration of the access token in seconds. + Must be set to a value less than or equal to 3600 (1 hour). If a value is + not specified, the token's lifetime will be set to a default value of one + hour. + + If a dict is provided, it must be of the same form as the protobuf + message :class:`~google.cloud.iam_credentials_v1.types.Duration` + retry (Optional[google.api_core.retry.Retry]): A retry object used + to retry requests. If ``None`` is specified, requests will not + be retried. + timeout (Optional[float]): The amount of time, in seconds, to wait + for the request to complete. Note that if ``retry`` is + specified, the timeout applies to each individual attempt. + metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata + that is provided to the method. + + Returns: + A :class:`~google.cloud.iam_credentials_v1.types.GenerateAccessTokenResponse` instance. + + Raises: + google.api_core.exceptions.GoogleAPICallError: If the request + failed for any reason. + google.api_core.exceptions.RetryError: If the request failed due + to a retryable error and retry attempts failed. + ValueError: If the parameters are invalid. + """ + # Wrap the transport method to add retry and timeout logic. + if "generate_access_token" not in self._inner_api_calls: + self._inner_api_calls[ + "generate_access_token" + ] = google.api_core.gapic_v1.method.wrap_method( + self.transport.generate_access_token, + default_retry=self._method_configs["GenerateAccessToken"].retry, + default_timeout=self._method_configs["GenerateAccessToken"].timeout, + client_info=self._client_info, + ) + + request = common_pb2.GenerateAccessTokenRequest( + name=name, scope=scope, delegates=delegates, lifetime=lifetime + ) + return self._inner_api_calls["generate_access_token"]( + request, retry=retry, timeout=timeout, metadata=metadata + ) + + def generate_id_token( + self, + name, + audience, + delegates=None, + include_email=None, + retry=google.api_core.gapic_v1.method.DEFAULT, + timeout=google.api_core.gapic_v1.method.DEFAULT, + metadata=None, + ): + """ + Generates an OpenID Connect ID token for a service account. + + Example: + >>> from google.cloud import iam_credentials_v1 + >>> + >>> client = iam_credentials_v1.IAMCredentialsClient() + >>> + >>> name = client.service_account_path('[PROJECT]', '[SERVICE_ACCOUNT]') + >>> + >>> # TODO: Initialize `audience`: + >>> audience = '' + >>> + >>> response = client.generate_id_token(name, audience) + + Args: + name (str): The resource name of the service account for which the credentials are + requested, in the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. + audience (str): The audience for the token, such as the API or account that this token + grants access to. + delegates (list[str]): The sequence of service accounts in a delegation chain. Each service + account must be granted the ``roles/iam.serviceAccountTokenCreator`` + role on its next service account in the chain. The last service account + in the chain must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on the service account + that is specified in the ``name`` field of the request. + + The delegates must have the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`` + include_email (bool): Include the service account email in the token. If set to ``true``, the + token will contain ``email`` and ``email_verified`` claims. + retry (Optional[google.api_core.retry.Retry]): A retry object used + to retry requests. If ``None`` is specified, requests will not + be retried. + timeout (Optional[float]): The amount of time, in seconds, to wait + for the request to complete. Note that if ``retry`` is + specified, the timeout applies to each individual attempt. + metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata + that is provided to the method. + + Returns: + A :class:`~google.cloud.iam_credentials_v1.types.GenerateIdTokenResponse` instance. + + Raises: + google.api_core.exceptions.GoogleAPICallError: If the request + failed for any reason. + google.api_core.exceptions.RetryError: If the request failed due + to a retryable error and retry attempts failed. + ValueError: If the parameters are invalid. + """ + # Wrap the transport method to add retry and timeout logic. + if "generate_id_token" not in self._inner_api_calls: + self._inner_api_calls[ + "generate_id_token" + ] = google.api_core.gapic_v1.method.wrap_method( + self.transport.generate_id_token, + default_retry=self._method_configs["GenerateIdToken"].retry, + default_timeout=self._method_configs["GenerateIdToken"].timeout, + client_info=self._client_info, + ) + + request = common_pb2.GenerateIdTokenRequest( + name=name, + audience=audience, + delegates=delegates, + include_email=include_email, + ) + return self._inner_api_calls["generate_id_token"]( + request, retry=retry, timeout=timeout, metadata=metadata + ) + + def sign_blob( + self, + name, + payload, + delegates=None, + retry=google.api_core.gapic_v1.method.DEFAULT, + timeout=google.api_core.gapic_v1.method.DEFAULT, + metadata=None, + ): + """ + Signs a blob using a service account's system-managed private key. + + Example: + >>> from google.cloud import iam_credentials_v1 + >>> + >>> client = iam_credentials_v1.IAMCredentialsClient() + >>> + >>> name = client.service_account_path('[PROJECT]', '[SERVICE_ACCOUNT]') + >>> + >>> # TODO: Initialize `payload`: + >>> payload = b'' + >>> + >>> response = client.sign_blob(name, payload) + + Args: + name (str): The resource name of the service account for which the credentials are + requested, in the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. + payload (bytes): The bytes to sign. + delegates (list[str]): The sequence of service accounts in a delegation chain. Each service + account must be granted the ``roles/iam.serviceAccountTokenCreator`` + role on its next service account in the chain. The last service account + in the chain must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on the service account + that is specified in the ``name`` field of the request. + + The delegates must have the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`` + retry (Optional[google.api_core.retry.Retry]): A retry object used + to retry requests. If ``None`` is specified, requests will not + be retried. + timeout (Optional[float]): The amount of time, in seconds, to wait + for the request to complete. Note that if ``retry`` is + specified, the timeout applies to each individual attempt. + metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata + that is provided to the method. + + Returns: + A :class:`~google.cloud.iam_credentials_v1.types.SignBlobResponse` instance. + + Raises: + google.api_core.exceptions.GoogleAPICallError: If the request + failed for any reason. + google.api_core.exceptions.RetryError: If the request failed due + to a retryable error and retry attempts failed. + ValueError: If the parameters are invalid. + """ + # Wrap the transport method to add retry and timeout logic. + if "sign_blob" not in self._inner_api_calls: + self._inner_api_calls[ + "sign_blob" + ] = google.api_core.gapic_v1.method.wrap_method( + self.transport.sign_blob, + default_retry=self._method_configs["SignBlob"].retry, + default_timeout=self._method_configs["SignBlob"].timeout, + client_info=self._client_info, + ) + + request = common_pb2.SignBlobRequest( + name=name, payload=payload, delegates=delegates + ) + return self._inner_api_calls["sign_blob"]( + request, retry=retry, timeout=timeout, metadata=metadata + ) + + def sign_jwt( + self, + name, + payload, + delegates=None, + retry=google.api_core.gapic_v1.method.DEFAULT, + timeout=google.api_core.gapic_v1.method.DEFAULT, + metadata=None, + ): + """ + Signs a JWT using a service account's system-managed private key. + + Example: + >>> from google.cloud import iam_credentials_v1 + >>> + >>> client = iam_credentials_v1.IAMCredentialsClient() + >>> + >>> name = client.service_account_path('[PROJECT]', '[SERVICE_ACCOUNT]') + >>> + >>> # TODO: Initialize `payload`: + >>> payload = '' + >>> + >>> response = client.sign_jwt(name, payload) + + Args: + name (str): The resource name of the service account for which the credentials are + requested, in the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. + payload (str): The JWT payload to sign: a JSON object that contains a JWT Claims Set. + delegates (list[str]): The sequence of service accounts in a delegation chain. Each service + account must be granted the ``roles/iam.serviceAccountTokenCreator`` + role on its next service account in the chain. The last service account + in the chain must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on the service account + that is specified in the ``name`` field of the request. + + The delegates must have the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`` + retry (Optional[google.api_core.retry.Retry]): A retry object used + to retry requests. If ``None`` is specified, requests will not + be retried. + timeout (Optional[float]): The amount of time, in seconds, to wait + for the request to complete. Note that if ``retry`` is + specified, the timeout applies to each individual attempt. + metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata + that is provided to the method. + + Returns: + A :class:`~google.cloud.iam_credentials_v1.types.SignJwtResponse` instance. + + Raises: + google.api_core.exceptions.GoogleAPICallError: If the request + failed for any reason. + google.api_core.exceptions.RetryError: If the request failed due + to a retryable error and retry attempts failed. + ValueError: If the parameters are invalid. + """ + # Wrap the transport method to add retry and timeout logic. + if "sign_jwt" not in self._inner_api_calls: + self._inner_api_calls[ + "sign_jwt" + ] = google.api_core.gapic_v1.method.wrap_method( + self.transport.sign_jwt, + default_retry=self._method_configs["SignJwt"].retry, + default_timeout=self._method_configs["SignJwt"].timeout, + client_info=self._client_info, + ) + + request = common_pb2.SignJwtRequest( + name=name, payload=payload, delegates=delegates + ) + return self._inner_api_calls["sign_jwt"]( + request, retry=retry, timeout=timeout, metadata=metadata + ) diff --git a/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client_config.py b/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client_config.py new file mode 100644 index 000000000000..35c007ca367f --- /dev/null +++ b/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client_config.py @@ -0,0 +1,43 @@ +config = { + "interfaces": { + "google.iam.credentials.v1.IAMCredentials": { + "retry_codes": { + "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], + "non_idempotent": [], + }, + "retry_params": { + "default": { + "initial_retry_delay_millis": 100, + "retry_delay_multiplier": 1.3, + "max_retry_delay_millis": 60000, + "initial_rpc_timeout_millis": 20000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 20000, + "total_timeout_millis": 600000, + } + }, + "methods": { + "GenerateAccessToken": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default", + }, + "GenerateIdToken": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default", + }, + "SignBlob": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default", + }, + "SignJwt": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default", + }, + }, + } + } +} diff --git a/iam/google/cloud/iam_credentials_v1/gapic/transports/__init__.py b/iam/google/cloud/iam_credentials_v1/gapic/transports/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/iam/google/cloud/iam_credentials_v1/gapic/transports/iam_credentials_grpc_transport.py b/iam/google/cloud/iam_credentials_v1/gapic/transports/iam_credentials_grpc_transport.py new file mode 100644 index 000000000000..c47617405d44 --- /dev/null +++ b/iam/google/cloud/iam_credentials_v1/gapic/transports/iam_credentials_grpc_transport.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2018 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 +# +# https://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 google.api_core.grpc_helpers + +from google.cloud.iam_credentials_v1.proto import iamcredentials_pb2_grpc + + +class IamCredentialsGrpcTransport(object): + """gRPC transport class providing stubs for + google.iam.credentials.v1 IAMCredentials API. + + The transport provides access to the raw gRPC stubs, + which can be used to take advantage of advanced + features of gRPC. + """ + + # The scopes needed to make gRPC calls to all of the methods defined + # in this service. + _OAUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + def __init__( + self, + channel=None, + credentials=None, + address="iamcredentials.googleapis.com:443", + ): + """Instantiate the transport class. + + Args: + channel (grpc.Channel): A ``Channel`` instance through + which to make calls. This argument is mutually exclusive + with ``credentials``; providing both will raise an exception. + credentials (google.auth.credentials.Credentials): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If none + are specified, the client will attempt to ascertain the + credentials from the environment. + address (str): The address where the service is hosted. + """ + # If both `channel` and `credentials` are specified, raise an + # exception (channels come with credentials baked in already). + if channel is not None and credentials is not None: + raise ValueError( + "The `channel` and `credentials` arguments are mutually " "exclusive." + ) + + # Create the channel. + if channel is None: + channel = self.create_channel(address=address, credentials=credentials) + + self._channel = channel + + # gRPC uses objects called "stubs" that are bound to the + # channel and provide a basic method for each RPC. + self._stubs = { + "iam_credentials_stub": iamcredentials_pb2_grpc.IAMCredentialsStub(channel) + } + + @classmethod + def create_channel( + cls, address="iamcredentials.googleapis.com:443", credentials=None + ): + """Create and return a gRPC channel object. + + Args: + address (str): The host for the channel to use. + credentials (~.Credentials): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + + Returns: + grpc.Channel: A gRPC channel object. + """ + return google.api_core.grpc_helpers.create_channel( + address, credentials=credentials, scopes=cls._OAUTH_SCOPES + ) + + @property + def channel(self): + """The gRPC channel used by the transport. + + Returns: + grpc.Channel: A gRPC channel object. + """ + return self._channel + + @property + def generate_access_token(self): + """Return the gRPC stub for {$apiMethod.name}. + + Generates an OAuth 2.0 access token for a service account. + + Returns: + Callable: A callable which accepts the appropriate + deserialized request object and returns a + deserialized response object. + """ + return self._stubs["iam_credentials_stub"].GenerateAccessToken + + @property + def generate_id_token(self): + """Return the gRPC stub for {$apiMethod.name}. + + Generates an OpenID Connect ID token for a service account. + + Returns: + Callable: A callable which accepts the appropriate + deserialized request object and returns a + deserialized response object. + """ + return self._stubs["iam_credentials_stub"].GenerateIdToken + + @property + def sign_blob(self): + """Return the gRPC stub for {$apiMethod.name}. + + Signs a blob using a service account's system-managed private key. + + Returns: + Callable: A callable which accepts the appropriate + deserialized request object and returns a + deserialized response object. + """ + return self._stubs["iam_credentials_stub"].SignBlob + + @property + def sign_jwt(self): + """Return the gRPC stub for {$apiMethod.name}. + + Signs a JWT using a service account's system-managed private key. + + Returns: + Callable: A callable which accepts the appropriate + deserialized request object and returns a + deserialized response object. + """ + return self._stubs["iam_credentials_stub"].SignJwt diff --git a/iam/google/cloud/iam_credentials_v1/proto/__init__.py b/iam/google/cloud/iam_credentials_v1/proto/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/iam/google/cloud/iam_credentials_v1/proto/common_pb2.py b/iam/google/cloud/iam_credentials_v1/proto/common_pb2.py new file mode 100644 index 000000000000..114c1603c108 --- /dev/null +++ b/iam/google/cloud/iam_credentials_v1/proto/common_pb2.py @@ -0,0 +1,805 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/iam/credentials/v1/common.proto + +import sys + +_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name="google/iam/credentials/v1/common.proto", + package="google.iam.credentials.v1", + syntax="proto3", + serialized_pb=_b( + '\n&google/iam/credentials/v1/common.proto\x12\x19google.iam.credentials.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto"y\n\x1aGenerateAccessTokenRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\tdelegates\x18\x02 \x03(\t\x12\r\n\x05scope\x18\x04 \x03(\t\x12+\n\x08lifetime\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration"d\n\x1bGenerateAccessTokenResponse\x12\x14\n\x0c\x61\x63\x63\x65ss_token\x18\x01 \x01(\t\x12/\n\x0b\x65xpire_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"C\n\x0fSignBlobRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\tdelegates\x18\x03 \x03(\t\x12\x0f\n\x07payload\x18\x05 \x01(\x0c"7\n\x10SignBlobResponse\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x13\n\x0bsigned_blob\x18\x04 \x01(\x0c"B\n\x0eSignJwtRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\tdelegates\x18\x03 \x03(\t\x12\x0f\n\x07payload\x18\x05 \x01(\t"5\n\x0fSignJwtResponse\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x12\n\nsigned_jwt\x18\x02 \x01(\t"b\n\x16GenerateIdTokenRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\tdelegates\x18\x02 \x03(\t\x12\x10\n\x08\x61udience\x18\x03 \x01(\t\x12\x15\n\rinclude_email\x18\x04 \x01(\x08"(\n\x17GenerateIdTokenResponse\x12\r\n\x05token\x18\x01 \x01(\tB\x8b\x01\n#com.google.cloud.iam.credentials.v1B\x19IAMCredentialsCommonProtoP\x01ZDgoogle.golang.org/genproto/googleapis/iam/credentials/v1;credentials\xf8\x01\x01\x62\x06proto3' + ), + dependencies=[ + google_dot_protobuf_dot_duration__pb2.DESCRIPTOR, + google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR, + ], +) + + +_GENERATEACCESSTOKENREQUEST = _descriptor.Descriptor( + name="GenerateAccessTokenRequest", + full_name="google.iam.credentials.v1.GenerateAccessTokenRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="google.iam.credentials.v1.GenerateAccessTokenRequest.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="delegates", + full_name="google.iam.credentials.v1.GenerateAccessTokenRequest.delegates", + index=1, + number=2, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="scope", + full_name="google.iam.credentials.v1.GenerateAccessTokenRequest.scope", + index=2, + number=4, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="lifetime", + full_name="google.iam.credentials.v1.GenerateAccessTokenRequest.lifetime", + index=3, + number=7, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=134, + serialized_end=255, +) + + +_GENERATEACCESSTOKENRESPONSE = _descriptor.Descriptor( + name="GenerateAccessTokenResponse", + full_name="google.iam.credentials.v1.GenerateAccessTokenResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="access_token", + full_name="google.iam.credentials.v1.GenerateAccessTokenResponse.access_token", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="expire_time", + full_name="google.iam.credentials.v1.GenerateAccessTokenResponse.expire_time", + index=1, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=257, + serialized_end=357, +) + + +_SIGNBLOBREQUEST = _descriptor.Descriptor( + name="SignBlobRequest", + full_name="google.iam.credentials.v1.SignBlobRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="google.iam.credentials.v1.SignBlobRequest.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="delegates", + full_name="google.iam.credentials.v1.SignBlobRequest.delegates", + index=1, + number=3, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="payload", + full_name="google.iam.credentials.v1.SignBlobRequest.payload", + index=2, + number=5, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b(""), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=359, + serialized_end=426, +) + + +_SIGNBLOBRESPONSE = _descriptor.Descriptor( + name="SignBlobResponse", + full_name="google.iam.credentials.v1.SignBlobResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key_id", + full_name="google.iam.credentials.v1.SignBlobResponse.key_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="signed_blob", + full_name="google.iam.credentials.v1.SignBlobResponse.signed_blob", + index=1, + number=4, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b(""), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=428, + serialized_end=483, +) + + +_SIGNJWTREQUEST = _descriptor.Descriptor( + name="SignJwtRequest", + full_name="google.iam.credentials.v1.SignJwtRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="google.iam.credentials.v1.SignJwtRequest.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="delegates", + full_name="google.iam.credentials.v1.SignJwtRequest.delegates", + index=1, + number=3, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="payload", + full_name="google.iam.credentials.v1.SignJwtRequest.payload", + index=2, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=485, + serialized_end=551, +) + + +_SIGNJWTRESPONSE = _descriptor.Descriptor( + name="SignJwtResponse", + full_name="google.iam.credentials.v1.SignJwtResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key_id", + full_name="google.iam.credentials.v1.SignJwtResponse.key_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="signed_jwt", + full_name="google.iam.credentials.v1.SignJwtResponse.signed_jwt", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=553, + serialized_end=606, +) + + +_GENERATEIDTOKENREQUEST = _descriptor.Descriptor( + name="GenerateIdTokenRequest", + full_name="google.iam.credentials.v1.GenerateIdTokenRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="google.iam.credentials.v1.GenerateIdTokenRequest.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="delegates", + full_name="google.iam.credentials.v1.GenerateIdTokenRequest.delegates", + index=1, + number=2, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="audience", + full_name="google.iam.credentials.v1.GenerateIdTokenRequest.audience", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="include_email", + full_name="google.iam.credentials.v1.GenerateIdTokenRequest.include_email", + index=3, + number=4, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=608, + serialized_end=706, +) + + +_GENERATEIDTOKENRESPONSE = _descriptor.Descriptor( + name="GenerateIdTokenResponse", + full_name="google.iam.credentials.v1.GenerateIdTokenResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="token", + full_name="google.iam.credentials.v1.GenerateIdTokenResponse.token", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None, + file=DESCRIPTOR, + ) + ], + extensions=[], + nested_types=[], + enum_types=[], + options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=708, + serialized_end=748, +) + +_GENERATEACCESSTOKENREQUEST.fields_by_name[ + "lifetime" +].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +_GENERATEACCESSTOKENRESPONSE.fields_by_name[ + "expire_time" +].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +DESCRIPTOR.message_types_by_name[ + "GenerateAccessTokenRequest" +] = _GENERATEACCESSTOKENREQUEST +DESCRIPTOR.message_types_by_name[ + "GenerateAccessTokenResponse" +] = _GENERATEACCESSTOKENRESPONSE +DESCRIPTOR.message_types_by_name["SignBlobRequest"] = _SIGNBLOBREQUEST +DESCRIPTOR.message_types_by_name["SignBlobResponse"] = _SIGNBLOBRESPONSE +DESCRIPTOR.message_types_by_name["SignJwtRequest"] = _SIGNJWTREQUEST +DESCRIPTOR.message_types_by_name["SignJwtResponse"] = _SIGNJWTRESPONSE +DESCRIPTOR.message_types_by_name["GenerateIdTokenRequest"] = _GENERATEIDTOKENREQUEST +DESCRIPTOR.message_types_by_name["GenerateIdTokenResponse"] = _GENERATEIDTOKENRESPONSE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +GenerateAccessTokenRequest = _reflection.GeneratedProtocolMessageType( + "GenerateAccessTokenRequest", + (_message.Message,), + dict( + DESCRIPTOR=_GENERATEACCESSTOKENREQUEST, + __module__="google.iam.credentials.v1.common_pb2", + __doc__="""Attributes: + name: + The resource name of the service account for which the + credentials are requested, in the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. + delegates: + The sequence of service accounts in a delegation chain. Each + service account must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on its next + service account in the chain. The last service account in the + chain must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on the service + account that is specified in the ``name`` field of the + request. The delegates must have the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`` + scope: + Code to identify the scopes to be included in the OAuth 2.0 + access token. See + https://developers.google.com/identity/protocols/googlescopes + for more information. At least one value required. + lifetime: + The desired lifetime duration of the access token in seconds. + Must be set to a value less than or equal to 3600 (1 hour). If + a value is not specified, the token's lifetime will be set to + a default value of one hour. + """, + # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.GenerateAccessTokenRequest) + ), +) +_sym_db.RegisterMessage(GenerateAccessTokenRequest) + +GenerateAccessTokenResponse = _reflection.GeneratedProtocolMessageType( + "GenerateAccessTokenResponse", + (_message.Message,), + dict( + DESCRIPTOR=_GENERATEACCESSTOKENRESPONSE, + __module__="google.iam.credentials.v1.common_pb2", + __doc__="""Attributes: + access_token: + The OAuth 2.0 access token. + expire_time: + Token expiration time. The expiration time is always set. + """, + # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.GenerateAccessTokenResponse) + ), +) +_sym_db.RegisterMessage(GenerateAccessTokenResponse) + +SignBlobRequest = _reflection.GeneratedProtocolMessageType( + "SignBlobRequest", + (_message.Message,), + dict( + DESCRIPTOR=_SIGNBLOBREQUEST, + __module__="google.iam.credentials.v1.common_pb2", + __doc__="""Attributes: + name: + The resource name of the service account for which the + credentials are requested, in the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. + delegates: + The sequence of service accounts in a delegation chain. Each + service account must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on its next + service account in the chain. The last service account in the + chain must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on the service + account that is specified in the ``name`` field of the + request. The delegates must have the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`` + payload: + The bytes to sign. + """, + # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.SignBlobRequest) + ), +) +_sym_db.RegisterMessage(SignBlobRequest) + +SignBlobResponse = _reflection.GeneratedProtocolMessageType( + "SignBlobResponse", + (_message.Message,), + dict( + DESCRIPTOR=_SIGNBLOBRESPONSE, + __module__="google.iam.credentials.v1.common_pb2", + __doc__="""Attributes: + key_id: + The ID of the key used to sign the blob. + signed_blob: + The signed blob. + """, + # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.SignBlobResponse) + ), +) +_sym_db.RegisterMessage(SignBlobResponse) + +SignJwtRequest = _reflection.GeneratedProtocolMessageType( + "SignJwtRequest", + (_message.Message,), + dict( + DESCRIPTOR=_SIGNJWTREQUEST, + __module__="google.iam.credentials.v1.common_pb2", + __doc__="""Attributes: + name: + The resource name of the service account for which the + credentials are requested, in the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. + delegates: + The sequence of service accounts in a delegation chain. Each + service account must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on its next + service account in the chain. The last service account in the + chain must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on the service + account that is specified in the ``name`` field of the + request. The delegates must have the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`` + payload: + The JWT payload to sign: a JSON object that contains a JWT + Claims Set. + """, + # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.SignJwtRequest) + ), +) +_sym_db.RegisterMessage(SignJwtRequest) + +SignJwtResponse = _reflection.GeneratedProtocolMessageType( + "SignJwtResponse", + (_message.Message,), + dict( + DESCRIPTOR=_SIGNJWTRESPONSE, + __module__="google.iam.credentials.v1.common_pb2", + __doc__="""Attributes: + key_id: + The ID of the key used to sign the JWT. + signed_jwt: + The signed JWT. + """, + # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.SignJwtResponse) + ), +) +_sym_db.RegisterMessage(SignJwtResponse) + +GenerateIdTokenRequest = _reflection.GeneratedProtocolMessageType( + "GenerateIdTokenRequest", + (_message.Message,), + dict( + DESCRIPTOR=_GENERATEIDTOKENREQUEST, + __module__="google.iam.credentials.v1.common_pb2", + __doc__="""Attributes: + name: + The resource name of the service account for which the + credentials are requested, in the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. + delegates: + The sequence of service accounts in a delegation chain. Each + service account must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on its next + service account in the chain. The last service account in the + chain must be granted the + ``roles/iam.serviceAccountTokenCreator`` role on the service + account that is specified in the ``name`` field of the + request. The delegates must have the following format: + ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`` + audience: + The audience for the token, such as the API or account that + this token grants access to. + include_email: + Include the service account email in the token. If set to + ``true``, the token will contain ``email`` and + ``email_verified`` claims. + """, + # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.GenerateIdTokenRequest) + ), +) +_sym_db.RegisterMessage(GenerateIdTokenRequest) + +GenerateIdTokenResponse = _reflection.GeneratedProtocolMessageType( + "GenerateIdTokenResponse", + (_message.Message,), + dict( + DESCRIPTOR=_GENERATEIDTOKENRESPONSE, + __module__="google.iam.credentials.v1.common_pb2", + __doc__="""Attributes: + token: + The OpenId Connect ID token. + """, + # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.GenerateIdTokenResponse) + ), +) +_sym_db.RegisterMessage(GenerateIdTokenResponse) + + +DESCRIPTOR.has_options = True +DESCRIPTOR._options = _descriptor._ParseOptions( + descriptor_pb2.FileOptions(), + _b( + "\n#com.google.cloud.iam.credentials.v1B\031IAMCredentialsCommonProtoP\001ZDgoogle.golang.org/genproto/googleapis/iam/credentials/v1;credentials\370\001\001" + ), +) +# @@protoc_insertion_point(module_scope) diff --git a/iam/google/cloud/iam_credentials_v1/proto/common_pb2_grpc.py b/iam/google/cloud/iam_credentials_v1/proto/common_pb2_grpc.py new file mode 100644 index 000000000000..07cb78fe03a9 --- /dev/null +++ b/iam/google/cloud/iam_credentials_v1/proto/common_pb2_grpc.py @@ -0,0 +1,2 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +import grpc diff --git a/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2.py b/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2.py new file mode 100644 index 000000000000..c2d28166144b --- /dev/null +++ b/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2.py @@ -0,0 +1,120 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/iam/credentials/v1/iamcredentials.proto + +import sys + +_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 +from google.cloud.iam_credentials_v1.proto import ( + common_pb2 as google_dot_iam_dot_credentials_dot_v1_dot_common__pb2, +) + + +DESCRIPTOR = _descriptor.FileDescriptor( + name="google/iam/credentials/v1/iamcredentials.proto", + package="google.iam.credentials.v1", + syntax="proto3", + serialized_pb=_b( + '\n.google/iam/credentials/v1/iamcredentials.proto\x12\x19google.iam.credentials.v1\x1a\x1cgoogle/api/annotations.proto\x1a&google/iam/credentials/v1/common.proto2\xe0\x05\n\x0eIAMCredentials\x12\xcc\x01\n\x13GenerateAccessToken\x12\x35.google.iam.credentials.v1.GenerateAccessTokenRequest\x1a\x36.google.iam.credentials.v1.GenerateAccessTokenResponse"F\x82\xd3\xe4\x93\x02@";/v1/{name=projects/*/serviceAccounts/*}:generateAccessToken:\x01*\x12\xbc\x01\n\x0fGenerateIdToken\x12\x31.google.iam.credentials.v1.GenerateIdTokenRequest\x1a\x32.google.iam.credentials.v1.GenerateIdTokenResponse"B\x82\xd3\xe4\x93\x02<"7/v1/{name=projects/*/serviceAccounts/*}:generateIdToken:\x01*\x12\xa0\x01\n\x08SignBlob\x12*.google.iam.credentials.v1.SignBlobRequest\x1a+.google.iam.credentials.v1.SignBlobResponse";\x82\xd3\xe4\x93\x02\x35"0/v1/{name=projects/*/serviceAccounts/*}:signBlob:\x01*\x12\x9c\x01\n\x07SignJwt\x12).google.iam.credentials.v1.SignJwtRequest\x1a*.google.iam.credentials.v1.SignJwtResponse":\x82\xd3\xe4\x93\x02\x34"//v1/{name=projects/*/serviceAccounts/*}:signJwt:\x01*B\x85\x01\n#com.google.cloud.iam.credentials.v1B\x13IAMCredentialsProtoP\x01ZDgoogle.golang.org/genproto/googleapis/iam/credentials/v1;credentials\xf8\x01\x01\x62\x06proto3' + ), + dependencies=[ + google_dot_api_dot_annotations__pb2.DESCRIPTOR, + google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.DESCRIPTOR, + ], +) + + +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + + +DESCRIPTOR.has_options = True +DESCRIPTOR._options = _descriptor._ParseOptions( + descriptor_pb2.FileOptions(), + _b( + "\n#com.google.cloud.iam.credentials.v1B\023IAMCredentialsProtoP\001ZDgoogle.golang.org/genproto/googleapis/iam/credentials/v1;credentials\370\001\001" + ), +) + +_IAMCREDENTIALS = _descriptor.ServiceDescriptor( + name="IAMCredentials", + full_name="google.iam.credentials.v1.IAMCredentials", + file=DESCRIPTOR, + index=0, + options=None, + serialized_start=148, + serialized_end=884, + methods=[ + _descriptor.MethodDescriptor( + name="GenerateAccessToken", + full_name="google.iam.credentials.v1.IAMCredentials.GenerateAccessToken", + index=0, + containing_service=None, + input_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._GENERATEACCESSTOKENREQUEST, + output_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._GENERATEACCESSTOKENRESPONSE, + options=_descriptor._ParseOptions( + descriptor_pb2.MethodOptions(), + _b( + '\202\323\344\223\002@";/v1/{name=projects/*/serviceAccounts/*}:generateAccessToken:\001*' + ), + ), + ), + _descriptor.MethodDescriptor( + name="GenerateIdToken", + full_name="google.iam.credentials.v1.IAMCredentials.GenerateIdToken", + index=1, + containing_service=None, + input_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._GENERATEIDTOKENREQUEST, + output_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._GENERATEIDTOKENRESPONSE, + options=_descriptor._ParseOptions( + descriptor_pb2.MethodOptions(), + _b( + '\202\323\344\223\002<"7/v1/{name=projects/*/serviceAccounts/*}:generateIdToken:\001*' + ), + ), + ), + _descriptor.MethodDescriptor( + name="SignBlob", + full_name="google.iam.credentials.v1.IAMCredentials.SignBlob", + index=2, + containing_service=None, + input_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._SIGNBLOBREQUEST, + output_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._SIGNBLOBRESPONSE, + options=_descriptor._ParseOptions( + descriptor_pb2.MethodOptions(), + _b( + '\202\323\344\223\0025"0/v1/{name=projects/*/serviceAccounts/*}:signBlob:\001*' + ), + ), + ), + _descriptor.MethodDescriptor( + name="SignJwt", + full_name="google.iam.credentials.v1.IAMCredentials.SignJwt", + index=3, + containing_service=None, + input_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._SIGNJWTREQUEST, + output_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._SIGNJWTRESPONSE, + options=_descriptor._ParseOptions( + descriptor_pb2.MethodOptions(), + _b( + '\202\323\344\223\0024"//v1/{name=projects/*/serviceAccounts/*}:signJwt:\001*' + ), + ), + ), + ], +) +_sym_db.RegisterServiceDescriptor(_IAMCREDENTIALS) + +DESCRIPTOR.services_by_name["IAMCredentials"] = _IAMCREDENTIALS + +# @@protoc_insertion_point(module_scope) diff --git a/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2_grpc.py b/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2_grpc.py new file mode 100644 index 000000000000..277e7249eef8 --- /dev/null +++ b/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2_grpc.py @@ -0,0 +1,116 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +import grpc + +from google.cloud.iam_credentials_v1.proto import ( + common_pb2 as google_dot_iam_dot_credentials_dot_v1_dot_common__pb2, +) + + +class IAMCredentialsStub(object): + """A service account is a special type of Google account that belongs to your + application or a virtual machine (VM), instead of to an individual end user. + Your application assumes the identity of the service account to call Google + APIs, so that the users aren't directly involved. + + Service account credentials are used to temporarily assume the identity + of the service account. Supported credential types include OAuth 2.0 access + tokens, OpenID Connect ID tokens, self-signed JSON Web Tokens (JWTs), and + more. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.GenerateAccessToken = channel.unary_unary( + "/google.iam.credentials.v1.IAMCredentials/GenerateAccessToken", + request_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateAccessTokenRequest.SerializeToString, + response_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateAccessTokenResponse.FromString, + ) + self.GenerateIdToken = channel.unary_unary( + "/google.iam.credentials.v1.IAMCredentials/GenerateIdToken", + request_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateIdTokenRequest.SerializeToString, + response_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateIdTokenResponse.FromString, + ) + self.SignBlob = channel.unary_unary( + "/google.iam.credentials.v1.IAMCredentials/SignBlob", + request_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignBlobRequest.SerializeToString, + response_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignBlobResponse.FromString, + ) + self.SignJwt = channel.unary_unary( + "/google.iam.credentials.v1.IAMCredentials/SignJwt", + request_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignJwtRequest.SerializeToString, + response_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignJwtResponse.FromString, + ) + + +class IAMCredentialsServicer(object): + """A service account is a special type of Google account that belongs to your + application or a virtual machine (VM), instead of to an individual end user. + Your application assumes the identity of the service account to call Google + APIs, so that the users aren't directly involved. + + Service account credentials are used to temporarily assume the identity + of the service account. Supported credential types include OAuth 2.0 access + tokens, OpenID Connect ID tokens, self-signed JSON Web Tokens (JWTs), and + more. + """ + + def GenerateAccessToken(self, request, context): + """Generates an OAuth 2.0 access token for a service account. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def GenerateIdToken(self, request, context): + """Generates an OpenID Connect ID token for a service account. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def SignBlob(self, request, context): + """Signs a blob using a service account's system-managed private key. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + def SignJwt(self, request, context): + """Signs a JWT using a service account's system-managed private key. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") + + +def add_IAMCredentialsServicer_to_server(servicer, server): + rpc_method_handlers = { + "GenerateAccessToken": grpc.unary_unary_rpc_method_handler( + servicer.GenerateAccessToken, + request_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateAccessTokenRequest.FromString, + response_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateAccessTokenResponse.SerializeToString, + ), + "GenerateIdToken": grpc.unary_unary_rpc_method_handler( + servicer.GenerateIdToken, + request_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateIdTokenRequest.FromString, + response_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateIdTokenResponse.SerializeToString, + ), + "SignBlob": grpc.unary_unary_rpc_method_handler( + servicer.SignBlob, + request_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignBlobRequest.FromString, + response_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignBlobResponse.SerializeToString, + ), + "SignJwt": grpc.unary_unary_rpc_method_handler( + servicer.SignJwt, + request_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignJwtRequest.FromString, + response_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignJwtResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + "google.iam.credentials.v1.IAMCredentials", rpc_method_handlers + ) + server.add_generic_rpc_handlers((generic_handler,)) diff --git a/iam/google/cloud/iam_credentials_v1/types.py b/iam/google/cloud/iam_credentials_v1/types.py new file mode 100644 index 000000000000..67e3278cc74f --- /dev/null +++ b/iam/google/cloud/iam_credentials_v1/types.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2018 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 +# +# https://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. + +from __future__ import absolute_import +import sys + +from google.api_core.protobuf_helpers import get_messages + +from google.api import http_pb2 +from google.cloud.iam_credentials_v1.proto import common_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf import duration_pb2 +from google.protobuf import timestamp_pb2 + +_shared_modules = [http_pb2, descriptor_pb2, duration_pb2, timestamp_pb2] + +_local_modules = [common_pb2] + +names = [] + +for module in _shared_modules: + for name, message in get_messages(module).items(): + setattr(sys.modules[__name__], name, message) + names.append(name) +for module in _local_modules: + for name, message in get_messages(module).items(): + message.__module__ = "google.cloud.iam_credentials_v1.types" + setattr(sys.modules[__name__], name, message) + names.append(name) + +__all__ = tuple(sorted(names)) diff --git a/iam/noxfile.py b/iam/noxfile.py new file mode 100644 index 000000000000..bfac9f4c2bce --- /dev/null +++ b/iam/noxfile.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2018 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 +# +# https://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. + +from __future__ import absolute_import +import os + +import nox + + +LOCAL_DEPS = (os.path.join("..", "api_core"), os.path.join("..", "core")) + +@nox.session(python="3.7") +def lint(session): + """Run linters. + + Returns a failure if the linters find linting errors or sufficiently + serious code quality issues. + """ + session.install("flake8", "black", *LOCAL_DEPS) + session.run( + "black", + "--check", + "google", + "tests", + "docs", + ) + session.run("flake8", "google", "tests") + + +@nox.session(python="3.6") +def blacken(session): + """Run black. + + Format code to uniform standard. + """ + session.install("black") + session.run( + "black", + "google", + "tests", + "docs", + ) + + +@nox.session(python="3.7") +def lint_setup_py(session): + """Verify that setup.py is valid (including RST check).""" + session.install("docutils", "pygments") + session.run("python", "setup.py", "check", "--restructuredtext", "--strict") + + +def default(session): + # Install all test dependencies, then install this package in-place. + session.install("mock", "pytest", "pytest-cov") + for local_dep in LOCAL_DEPS: + session.install("-e", local_dep) + session.install("-e", ".") + + # Run py.test against the unit tests. + session.run( + "py.test", + "--quiet", + "--cov=google.cloud", + "--cov=tests.unit", + "--cov-append", + "--cov-config=.coveragerc", + "--cov-report=", + "--cov-fail-under=97", + os.path.join("tests", "unit"), + *session.posargs, + ) + + +@nox.session(python=["2.7", "3.5", "3.6", "3.7"]) +def unit(session): + """Run the unit test suite.""" + default(session) + + +@nox.session(python=["2.7", "3.7"]) +def system(session): + """Run the system test suite.""" + system_test_path = os.path.join("tests", "system.py") + system_test_folder_path = os.path.join("tests", "system") + # Sanity check: Only run tests if the environment variable is set. + if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): + session.skip("Credentials must be set via environment variable") + + system_test_exists = os.path.exists(system_test_path) + system_test_folder_exists = os.path.exists(system_test_folder_path) + # Sanity check: only run tests if found. + if not system_test_exists and not system_test_folder_exists: + session.skip("System tests were not found") + + # Use pre-release gRPC for system tests. + session.install("--pre", "grpcio") + + # Install all test dependencies, then install this package into the + # virtualenv's dist-packages. + session.install("mock", "pytest") + for local_dep in LOCAL_DEPS: + session.install("-e", local_dep) + session.install("-e", "../test_utils/") + session.install("-e", ".") + + # Run py.test against the system tests. + if system_test_exists: + session.run("py.test", "--quiet", system_test_path, *session.posargs) + if system_test_folder_exists: + session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) + + +@nox.session(python="3.7") +def cover(session): + """Run the final coverage report. + + This outputs the coverage report aggregating coverage from the unit + test runs (not system test runs), and then erases coverage data. + """ + session.install("coverage", "pytest-cov") + session.run("coverage", "report", "--show-missing", "--fail-under=100") + + session.run("coverage", "erase") diff --git a/iam/setup.cfg b/iam/setup.cfg new file mode 100644 index 000000000000..2a9acf13daa9 --- /dev/null +++ b/iam/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal = 1 diff --git a/iam/setup.py b/iam/setup.py new file mode 100644 index 000000000000..8a4066ddd536 --- /dev/null +++ b/iam/setup.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2018 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 +# +# https://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 io +import os + +import setuptools + +name = 'google-cloud-iam' +description = 'IAM Service Account Credentials API client library' +version = '0.1.0' +release_status = '3 - Alpha' +dependencies = [ + 'google-api-core[grpc] >= 1.6.0, < 2.0.0dev', + 'enum34; python_version < "3.4"', +] + +package_root = os.path.abspath(os.path.dirname(__file__)) + +readme_filename = os.path.join(package_root, 'README.rst') +with io.open(readme_filename, encoding='utf-8') as readme_file: + readme = readme_file.read() + +packages = [ + package for package in setuptools.find_packages() + if package.startswith('google') +] + +namespaces = ['google'] +if 'google.cloud' in packages: + namespaces.append('google.cloud') + +setuptools.setup( + name=name, + version=version, + description=description, + long_description=readme, + author='Google LLC', + author_email='googleapis-packages@google.com', + license='Apache 2.0', + url='https://github.com/GoogleCloudPlatform/google-cloud-python', + classifiers=[ + release_status, + 'Intended Audience :: Developers', + 'License :: OSI Approved :: Apache Software License', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Operating System :: OS Independent', + 'Topic :: Internet', + ], + platforms='Posix; MacOS X; Windows', + packages=packages, + namespace_packages=namespaces, + install_requires=dependencies, + python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*', + include_package_data=True, + zip_safe=False, +) diff --git a/iam/synth.metadata b/iam/synth.metadata new file mode 100644 index 000000000000..ad280fa23372 --- /dev/null +++ b/iam/synth.metadata @@ -0,0 +1,39 @@ +{ + "updateTime": "2018-12-12T18:49:12.183864Z", + "sources": [ + { + "generator": { + "name": "artman", + "version": "0.16.2", + "dockerImage": "googleapis/artman@sha256:2f6b261ee7fe1aedf238991c93a20b3820de37a343d0cacf3e3e9555c2aaf2ea" + } + }, + { + "git": { + "name": "googleapis", + "remote": "https://github.com/googleapis/googleapis.git", + "sha": "7260ddc159d9b412b08e71e9cf4d859b4438dc55", + "internalRef": "225211827" + } + }, + { + "template": { + "name": "python_library", + "origin": "synthtool.gcp", + "version": "2018.12.6" + } + } + ], + "destinations": [ + { + "client": { + "source": "googleapis", + "apiName": "iam", + "apiVersion": "v1", + "language": "python", + "generator": "gapic", + "config": "google/iam/credentials/artman_iamcredentials_v1.yaml" + } + } + ] +} \ No newline at end of file diff --git a/iam/synth.py b/iam/synth.py new file mode 100644 index 000000000000..94833c6c9bf9 --- /dev/null +++ b/iam/synth.py @@ -0,0 +1,68 @@ +# Copyright 2018 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 +# limitations under the License. + +"""This script is used to synthesize generated parts of this library.""" + +import synthtool as s +from synthtool import gcp + +gapic = gcp.GAPICGenerator() +common = gcp.CommonTemplates() + +# ---------------------------------------------------------------------------- +# Generate automl GAPIC layer +# ---------------------------------------------------------------------------- +library = gapic.py_library( + "iam", + "v1", + config_path="/google/iam/credentials/artman_iamcredentials_v1.yaml", + artman_output_name="iamcredentials-v1" +) + +excludes = [ + "README.rst", + "setup.py", + "docs/index.rst", + "nox.py", +] +s.copy(library, excludes=excludes) + +s.replace( + "google/**/*.py", + "google-cloud-iamcredentials", + "google-cloud-iam" +) +s.replace( + "docs/**/*.py", + "google-cloud-iamcredentials", + "google-cloud-iam" +) + +s.replace( + "**/*.py", + "from google\.iam\.credentials\.v1 import common_pb2", + "from google.cloud.iam_credentials_v1.proto import common_pb2" +) +s.replace( + "**/*.py", + "from google\.iam\.credentials\.v1 import iamcredentials_pb2_grpc", + "from google.cloud.iam_credentials_v1.proto import iamcredentials_pb2_grpc" +) +# ---------------------------------------------------------------------------- +# Add templated files +# ---------------------------------------------------------------------------- +templated_files = common.py_library(unit_cov_level=97, cov_level=100) +s.move(templated_files) + +s.shell.run(["nox", "-s", "blacken"], hide_output=False) diff --git a/iam/tests/unit/gapic/v1/test_iam_credentials_client_v1.py b/iam/tests/unit/gapic/v1/test_iam_credentials_client_v1.py new file mode 100644 index 000000000000..4b5a98088ff7 --- /dev/null +++ b/iam/tests/unit/gapic/v1/test_iam_credentials_client_v1.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +# +# Copyright 2018 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 +# +# https://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. +"""Unit tests.""" + +import mock +import pytest + +from google.cloud import iam_credentials_v1 +from google.cloud.iam_credentials_v1.proto import common_pb2 + + +class MultiCallableStub(object): + """Stub for the grpc.UnaryUnaryMultiCallable interface.""" + + def __init__(self, method, channel_stub): + self.method = method + self.channel_stub = channel_stub + + def __call__(self, request, timeout=None, metadata=None, credentials=None): + self.channel_stub.requests.append((self.method, request)) + + response = None + if self.channel_stub.responses: + response = self.channel_stub.responses.pop() + + if isinstance(response, Exception): + raise response + + if response: + return response + + +class ChannelStub(object): + """Stub for the grpc.Channel interface.""" + + def __init__(self, responses=[]): + self.responses = responses + self.requests = [] + + def unary_unary(self, method, request_serializer=None, response_deserializer=None): + return MultiCallableStub(method, self) + + +class CustomException(Exception): + pass + + +class TestIAMCredentialsClient(object): + def test_generate_access_token(self): + # Setup Expected Response + access_token = "accessToken-1938933922" + expected_response = {"access_token": access_token} + expected_response = common_pb2.GenerateAccessTokenResponse(**expected_response) + + # Mock the API response + channel = ChannelStub(responses=[expected_response]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = iam_credentials_v1.IAMCredentialsClient() + + # Setup Request + name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") + scope = [] + + response = client.generate_access_token(name, scope) + assert expected_response == response + + assert len(channel.requests) == 1 + expected_request = common_pb2.GenerateAccessTokenRequest(name=name, scope=scope) + actual_request = channel.requests[0][1] + assert expected_request == actual_request + + def test_generate_access_token_exception(self): + # Mock the API response + channel = ChannelStub(responses=[CustomException()]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = iam_credentials_v1.IAMCredentialsClient() + + # Setup request + name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") + scope = [] + + with pytest.raises(CustomException): + client.generate_access_token(name, scope) + + def test_generate_id_token(self): + # Setup Expected Response + token = "token110541305" + expected_response = {"token": token} + expected_response = common_pb2.GenerateIdTokenResponse(**expected_response) + + # Mock the API response + channel = ChannelStub(responses=[expected_response]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = iam_credentials_v1.IAMCredentialsClient() + + # Setup Request + name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") + audience = "audience975628804" + + response = client.generate_id_token(name, audience) + assert expected_response == response + + assert len(channel.requests) == 1 + expected_request = common_pb2.GenerateIdTokenRequest( + name=name, audience=audience + ) + actual_request = channel.requests[0][1] + assert expected_request == actual_request + + def test_generate_id_token_exception(self): + # Mock the API response + channel = ChannelStub(responses=[CustomException()]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = iam_credentials_v1.IAMCredentialsClient() + + # Setup request + name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") + audience = "audience975628804" + + with pytest.raises(CustomException): + client.generate_id_token(name, audience) + + def test_sign_blob(self): + # Setup Expected Response + key_id = "keyId-1134673157" + signed_blob = b"-32" + expected_response = {"key_id": key_id, "signed_blob": signed_blob} + expected_response = common_pb2.SignBlobResponse(**expected_response) + + # Mock the API response + channel = ChannelStub(responses=[expected_response]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = iam_credentials_v1.IAMCredentialsClient() + + # Setup Request + name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") + payload = b"-114" + + response = client.sign_blob(name, payload) + assert expected_response == response + + assert len(channel.requests) == 1 + expected_request = common_pb2.SignBlobRequest(name=name, payload=payload) + actual_request = channel.requests[0][1] + assert expected_request == actual_request + + def test_sign_blob_exception(self): + # Mock the API response + channel = ChannelStub(responses=[CustomException()]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = iam_credentials_v1.IAMCredentialsClient() + + # Setup request + name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") + payload = b"-114" + + with pytest.raises(CustomException): + client.sign_blob(name, payload) + + def test_sign_jwt(self): + # Setup Expected Response + key_id = "keyId-1134673157" + signed_jwt = "signedJwt-979546844" + expected_response = {"key_id": key_id, "signed_jwt": signed_jwt} + expected_response = common_pb2.SignJwtResponse(**expected_response) + + # Mock the API response + channel = ChannelStub(responses=[expected_response]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = iam_credentials_v1.IAMCredentialsClient() + + # Setup Request + name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") + payload = "-114" + + response = client.sign_jwt(name, payload) + assert expected_response == response + + assert len(channel.requests) == 1 + expected_request = common_pb2.SignJwtRequest(name=name, payload=payload) + actual_request = channel.requests[0][1] + assert expected_request == actual_request + + def test_sign_jwt_exception(self): + # Mock the API response + channel = ChannelStub(responses=[CustomException()]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = iam_credentials_v1.IAMCredentialsClient() + + # Setup request + name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") + payload = "-114" + + with pytest.raises(CustomException): + client.sign_jwt(name, payload)