Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Unified Diff: third_party/google-endpoints/apitools/scripts/oauth2l.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/google-endpoints/apitools/scripts/oauth2l.py
diff --git a/third_party/google-endpoints/apitools/scripts/oauth2l.py b/third_party/google-endpoints/apitools/scripts/oauth2l.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd130644d29e9f3ff855f3efb8a708125c365515
--- /dev/null
+++ b/third_party/google-endpoints/apitools/scripts/oauth2l.py
@@ -0,0 +1,324 @@
+#
+# Copyright 2015 Google Inc.
+#
+# 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.
+
+"""Command-line utility for fetching/inspecting credentials.
+
+oauth2l (pronounced "oauthtool") is a small utility for fetching
+credentials, or inspecting existing credentials. Here we demonstrate
+some sample use:
+
+ $ oauth2l fetch userinfo.email bigquery compute
+ Fetched credentials of type:
+ oauth2client.client.OAuth2Credentials
+ Access token:
+ ya29.abcdefghijklmnopqrstuvwxyz123yessirree
+ $ oauth2l header userinfo.email
+ Authorization: Bearer ya29.zyxwvutsrqpnmolkjihgfedcba
+ $ oauth2l validate thisisnotatoken
+ <exit status: 1>
+ $ oauth2l validate ya29.zyxwvutsrqpnmolkjihgfedcba
+ $ oauth2l scopes ya29.abcdefghijklmnopqrstuvwxyz123yessirree
+ https://www.googleapis.com/auth/bigquery
+ https://www.googleapis.com/auth/compute
+ https://www.googleapis.com/auth/userinfo.email
+
+The `header` command is designed to be easy to use with `curl`:
+
+ $ curl "$(oauth2l header bigquery)" \
+ 'https://www.googleapis.com/bigquery/v2/projects'
+
+The token can also be printed in other formats, for easy chaining
+into other programs:
+
+ $ oauth2l fetch -f json_compact userinfo.email
+ <one-line JSON object with credential information>
+ $ oauth2l fetch -f bare drive
+ ya29.suchT0kenManyCredentialsW0Wokyougetthepoint
+
+"""
+
+import httplib
+import json
+import logging
+import os
+import pkgutil
+import sys
+import textwrap
+
+import gflags as flags
+from google.apputils import appcommands
+import oauth2client.client
+
+import apitools.base.py as apitools_base
+from apitools.base.py import cli as apitools_cli
+
+FLAGS = flags.FLAGS
+# We could use a generated client here, but it's used for precisely
+# one URL, with one parameter and no worries about URL encoding. Let's
+# go with simple.
+_OAUTH2_TOKENINFO_TEMPLATE = (
+ 'https://www.googleapis.com/oauth2/v2/tokeninfo'
+ '?access_token={access_token}'
+)
+
+
+flags.DEFINE_string(
+ 'client_secrets', '',
+ 'If specified, use the client ID/secret from the named '
+ 'file, which should be a client_secrets.json file as downloaded '
+ 'from the Developer Console.')
+flags.DEFINE_string(
+ 'credentials_filename', '',
+ '(optional) Filename for fetching/storing credentials.')
+flags.DEFINE_string(
+ 'service_account_json_keyfile', '',
+ 'Filename for a JSON service account key downloaded from the Developer '
+ 'Console.')
+
+
+def GetDefaultClientInfo():
+ client_secrets = json.loads(pkgutil.get_data(
+ 'apitools.data', 'apitools_client_secrets.json'))['installed']
+ return {
+ 'client_id': client_secrets['client_id'],
+ 'client_secret': client_secrets['client_secret'],
+ 'user_agent': 'apitools/0.2 oauth2l/0.1',
+ }
+
+
+def GetClientInfoFromFlags():
+ """Fetch client info from FLAGS."""
+ if FLAGS.client_secrets:
+ client_secrets_path = os.path.expanduser(FLAGS.client_secrets)
+ if not os.path.exists(client_secrets_path):
+ raise ValueError('Cannot find file: %s' % FLAGS.client_secrets)
+ with open(client_secrets_path) as client_secrets_file:
+ client_secrets = json.load(client_secrets_file)
+ if 'installed' not in client_secrets:
+ raise ValueError('Provided client ID must be for an installed app')
+ client_secrets = client_secrets['installed']
+ return {
+ 'client_id': client_secrets['client_id'],
+ 'client_secret': client_secrets['client_secret'],
+ 'user_agent': 'apitools/0.2 oauth2l/0.1',
+ }
+ else:
+ return GetDefaultClientInfo()
+
+
+def _ExpandScopes(scopes):
+ scope_prefix = 'https://www.googleapis.com/auth/'
+ return [s if s.startswith('https://') else scope_prefix + s
+ for s in scopes]
+
+
+def _PrettyJson(data):
+ return json.dumps(data, sort_keys=True, indent=4, separators=(',', ': '))
+
+
+def _CompactJson(data):
+ return json.dumps(data, sort_keys=True, separators=(',', ':'))
+
+
+def _Format(fmt, credentials):
+ """Format credentials according to fmt."""
+ if fmt == 'bare':
+ return credentials.access_token
+ elif fmt == 'header':
+ return 'Authorization: Bearer %s' % credentials.access_token
+ elif fmt == 'json':
+ return _PrettyJson(json.loads(credentials.to_json()))
+ elif fmt == 'json_compact':
+ return _CompactJson(json.loads(credentials.to_json()))
+ elif fmt == 'pretty':
+ format_str = textwrap.dedent('\n'.join([
+ 'Fetched credentials of type:',
+ ' {credentials_type.__module__}.{credentials_type.__name__}',
+ 'Access token:',
+ ' {credentials.access_token}',
+ ]))
+ return format_str.format(credentials=credentials,
+ credentials_type=type(credentials))
+ raise ValueError('Unknown format: {}'.format(fmt))
+
+_FORMATS = set(('bare', 'header', 'json', 'json_compact', 'pretty'))
+
+
+def _GetTokenScopes(access_token):
+ """Return the list of valid scopes for the given token as a list."""
+ url = _OAUTH2_TOKENINFO_TEMPLATE.format(access_token=access_token)
+ response = apitools_base.MakeRequest(
+ apitools_base.GetHttp(), apitools_base.Request(url))
+ if response.status_code not in [httplib.OK, httplib.BAD_REQUEST]:
+ raise apitools_base.HttpError.FromResponse(response)
+ if response.status_code == httplib.BAD_REQUEST:
+ return []
+ return json.loads(response.content)['scope'].split(' ')
+
+
+def _ValidateToken(access_token):
+ """Return True iff the provided access token is valid."""
+ return bool(_GetTokenScopes(access_token))
+
+
+def FetchCredentials(scopes, client_info=None, credentials_filename=None):
+ """Fetch a credential for the given client_info and scopes."""
+ client_info = client_info or GetClientInfoFromFlags()
+ scopes = _ExpandScopes(scopes)
+ if not scopes:
+ raise ValueError('No scopes provided')
+ credentials_filename = credentials_filename or FLAGS.credentials_filename
+ # TODO(craigcitro): Remove this logging nonsense once we quiet the
+ # spurious logging in oauth2client.
+ old_level = logging.getLogger().level
+ logging.getLogger().setLevel(logging.ERROR)
+ credentials = apitools_base.GetCredentials(
+ 'oauth2l', scopes, credentials_filename=credentials_filename,
+ service_account_json_keyfile=FLAGS.service_account_json_keyfile,
+ oauth2client_args='', **client_info)
+ logging.getLogger().setLevel(old_level)
+ if not _ValidateToken(credentials.access_token):
+ credentials.refresh(apitools_base.GetHttp())
+ return credentials
+
+
+class _Email(apitools_cli.NewCmd):
+
+ """Get user email."""
+
+ usage = 'email <access_token>'
+
+ def RunWithArgs(self, access_token):
+ """Print the email address for this token, if possible."""
+ userinfo = apitools_base.GetUserinfo(
+ oauth2client.client.AccessTokenCredentials(access_token,
+ 'oauth2l/1.0'))
+ user_email = userinfo.get('email')
+ if user_email:
+ print user_email
+
+
+class _Fetch(apitools_cli.NewCmd):
+
+ """Fetch credentials."""
+
+ usage = 'fetch <scope> [<scope> ...]'
+
+ def __init__(self, name, flag_values):
+ super(_Fetch, self).__init__(name, flag_values)
+ flags.DEFINE_enum(
+ 'credentials_format', 'pretty', sorted(_FORMATS),
+ 'Output format for token.',
+ short_name='f', flag_values=flag_values)
+
+ def RunWithArgs(self, *scopes):
+ """Fetch a valid access token and display it."""
+ credentials = FetchCredentials(scopes)
+ print _Format(FLAGS.credentials_format.lower(), credentials)
+
+
+class _Header(apitools_cli.NewCmd):
+
+ """Print credentials for a header."""
+
+ usage = 'header <scope> [<scope> ...]'
+
+ def RunWithArgs(self, *scopes):
+ """Fetch a valid access token and display it formatted for a header."""
+ print _Format('header', FetchCredentials(scopes))
+
+
+class _Scopes(apitools_cli.NewCmd):
+
+ """Get the list of scopes for a token."""
+
+ usage = 'scopes <access_token>'
+
+ def RunWithArgs(self, access_token):
+ """Print the list of scopes for a valid token."""
+ scopes = _GetTokenScopes(access_token)
+ if not scopes:
+ return 1
+ for scope in sorted(scopes):
+ print scope
+
+
+class _Userinfo(apitools_cli.NewCmd):
+
+ """Get userinfo."""
+
+ usage = 'userinfo <access_token>'
+
+ def __init__(self, name, flag_values):
+ super(_Userinfo, self).__init__(name, flag_values)
+ flags.DEFINE_enum(
+ 'format', 'json', sorted(('json', 'json_compact')),
+ 'Output format for userinfo.',
+ short_name='f', flag_values=flag_values)
+
+ def RunWithArgs(self, access_token):
+ """Print the userinfo for this token (if we have the right scopes)."""
+ userinfo = apitools_base.GetUserinfo(
+ oauth2client.client.AccessTokenCredentials(access_token,
+ 'oauth2l/1.0'))
+ if FLAGS.format == 'json':
+ print _PrettyJson(userinfo)
+ else:
+ print _CompactJson(userinfo)
+
+
+class _Validate(apitools_cli.NewCmd):
+
+ """Validate a token."""
+
+ usage = 'validate <access_token>'
+
+ def RunWithArgs(self, access_token):
+ """Validate an access token. Exits with 0 if valid, 1 otherwise."""
+ return 1 - (_ValidateToken(access_token))
+
+
+def run_main(): # pylint:disable=invalid-name
+ """Function to be used as setuptools script entry point."""
+ # Put the flags for this module somewhere the flags module will look
+ # for them.
+
+ # pylint:disable=protected-access
+ new_name = flags._GetMainModule()
+ sys.modules[new_name] = sys.modules['__main__']
+ for flag in FLAGS.FlagsByModuleDict().get(__name__, []):
+ FLAGS._RegisterFlagByModule(new_name, flag)
+ for key_flag in FLAGS.KeyFlagsByModuleDict().get(__name__, []):
+ FLAGS._RegisterKeyFlagForModule(new_name, key_flag)
+ # pylint:enable=protected-access
+
+ # Now set __main__ appropriately so that appcommands will be
+ # happy.
+ sys.modules['__main__'] = sys.modules[__name__]
+ appcommands.Run()
+ sys.modules['__main__'] = sys.modules.pop(new_name)
+
+
+def main(unused_argv):
+ appcommands.AddCmd('email', _Email)
+ appcommands.AddCmd('fetch', _Fetch)
+ appcommands.AddCmd('header', _Header)
+ appcommands.AddCmd('scopes', _Scopes)
+ appcommands.AddCmd('userinfo', _Userinfo)
+ appcommands.AddCmd('validate', _Validate)
+
+
+if __name__ == '__main__':
+ appcommands.Run()

Powered by Google App Engine
This is Rietveld 408576698