File: //proc/thread-self/root/proc/thread-self/root/usr/lib/google-cloud-sdk/lib/surface/auth/login.py
# -*- coding: utf-8 -*- #
# Copyright 2013 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The auth command gets tokens via oauth2."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import textwrap
from googlecloudsdk.api_lib.auth import exceptions as auth_exceptions
from googlecloudsdk.api_lib.auth import util as auth_util
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions as calliope_exceptions
from googlecloudsdk.command_lib.auth import auth_util as command_auth_util
from googlecloudsdk.command_lib.util import check_browser
from googlecloudsdk.core import config
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
from googlecloudsdk.core.console import console_io
from googlecloudsdk.core.credentials import devshell as c_devshell
from googlecloudsdk.core.credentials import gce as c_gce
from googlecloudsdk.core.credentials import store as c_store
from google.auth import jwt
class Login(base.Command):
"""Authorize gcloud to access the Cloud Platform with Google user credentials.
Obtains access credentials for your user account via a web-based authorization
flow. When this command completes successfully, it sets the active account
in the current configuration to the account specified. If no configuration
exists, it creates a configuration named default.
If valid credentials for an account are already available from a prior
authorization, the account is set to active without rerunning the flow.
Use `gcloud auth list` to view credentialed accounts.
If you'd rather authorize without a web browser but still interact with
the command line, use the `--no-launch-browser` flag. To authorize without
a web browser and non-interactively, create a service account with the
appropriate scopes using the
[Google Cloud Platform Console](https://console.cloud.google.com) and use
`gcloud auth activate-service-account` with the corresponding JSON key file.
For more information on authorization and credential types, see:
[](https://cloud.google.com/sdk/docs/authorizing).
## EXAMPLES
To obtain access credentials for your user account, run:
$ {command}
"""
@staticmethod
def Args(parser):
"""Set args for gcloud auth."""
parser.add_argument(
'--launch-browser',
action='store_true', default=True, dest='launch_browser',
help='Launch a browser for authorization. If not enabled or if it '
'is not possible to launch a browser, prints a URL to standard output '
'to be copied.')
parser.add_argument(
'--activate', action='store_true', default=True,
help='Set the new account to active.')
# --do-not-activate for (hidden) backwards compatibility.
parser.add_argument(
'--do-not-activate', action='store_false', dest='activate',
hidden=True,
help='THIS ARGUMENT NEEDS HELP TEXT.')
parser.add_argument(
'--brief', action='store_true',
help='Minimal user output.')
parser.add_argument(
'--force', action='store_true',
help='Re-run the web authorization flow even if the given account has '
'valid credentials.')
parser.add_argument(
'--enable-gdrive-access', action='store_true',
help='Enable Google Drive access.')
parser.add_argument(
'--update-adc',
action='store_true',
default=False,
help='Write the obtained credentials to the well-known location for '
'Application Default Credentials (ADC). Run '
'$ gcloud auth application-default --help to learn more about ADC. '
'Any credentials previously generated by '
'`gcloud auth application-default login` will be overwritten.')
parser.add_argument(
'--add-quota-project-to-adc',
action='store_true',
default=False,
hidden=True,
help="Read the project from gcloud's context and write to application "
'default credentials as the quota project. Use this flag only '
'when --update-adc is specified.')
parser.add_argument(
'account', nargs='?', help='User account used for authorization.')
parser.add_argument(
'--use-oauth2client',
action='store_true',
default=True,
hidden=True,
help='The gcloud command-line tool is using google-auth-library-python '
'as its new auth library during login. Use this flag to switch '
'back to the oauth2client.')
parser.display_info.AddFormat('none')
def Run(self, args):
"""Run the authentication command."""
scopes = config.CLOUDSDK_SCOPES
# Add REAUTH scope in case the user has 2fact activated.
# This scope is only used here and when refreshing the access token.
scopes += (config.REAUTH_SCOPE,)
if args.enable_gdrive_access:
scopes += (auth_util.GOOGLE_DRIVE_SCOPE,)
if c_devshell.IsDevshellEnvironment():
if c_devshell.HasDevshellAuth():
message = textwrap.dedent("""
You are already authenticated with gcloud when running
inside the Cloud Shell and so do not need to run this
command. Do you wish to proceed anyway?
""")
answer = console_io.PromptContinue(message=message)
if not answer:
return None
elif c_gce.Metadata().connected:
message = textwrap.dedent("""
You are running on a Google Compute Engine virtual machine.
It is recommended that you use service accounts for authentication.
You can run:
$ gcloud config set account `ACCOUNT`
to switch accounts if necessary.
Your credentials may be visible to others with access to this
virtual machine. Are you sure you want to authenticate with
your personal account?
""")
answer = console_io.PromptContinue(message=message)
if not answer:
return None
account = args.account
if account and not args.force:
try:
creds = c_store.Load(account=account, scopes=scopes)
except c_store.Error:
creds = None
if creds:
# Account already has valid creds, just switch to it.
log.warning('Re-using locally stored credentials for [{}]. '
'To fetch new credentials, re-run the command with the '
'`--force` flag.'.format(account))
return LoginAs(account, creds, args.project, args.activate, args.brief,
args.update_adc, args.add_quota_project_to_adc)
# No valid creds, do the web flow.
launch_browser = check_browser.ShouldLaunchBrowser(args.launch_browser)
if args.use_oauth2client:
creds = auth_util.DoInstalledAppBrowserFlow(launch_browser, scopes)
web_flow_account = creds.id_token['email']
else:
creds = auth_util.DoInstalledAppBrowserFlowGoogleAuth(
launch_browser, scopes)
decoded_id_token = jwt.decode(creds.id_token, verify=False)
web_flow_account = decoded_id_token['email']
if account and account.lower() != web_flow_account.lower():
raise auth_exceptions.WrongAccountError(
'You attempted to log in as account [{account}] but the received '
'credentials were for account [{web_flow_account}].\n\n'
'Please check that your browser is logged in as account [{account}] '
'and that you are using the correct browser profile.'.format(
account=account, web_flow_account=web_flow_account))
account = web_flow_account
# We got new creds, and they are for the correct user.
c_store.Store(creds, account, scopes)
return LoginAs(account, creds, args.project, args.activate, args.brief,
args.update_adc, args.add_quota_project_to_adc)
def LoginAs(account, creds, project, activate, brief, update_adc,
add_quota_project_to_adc):
"""Logs in with valid credentials."""
_ValidateADCFlags(update_adc, add_quota_project_to_adc)
if update_adc:
_UpdateADC(creds, add_quota_project_to_adc)
if not activate:
return creds
properties.PersistProperty(properties.VALUES.core.account, account)
if project:
properties.PersistProperty(properties.VALUES.core.project, project)
if not brief:
log.status.write(
'\nYou are now logged in as [{account}].\n'
'Your current project is [{project}]. You can change this setting '
'by running:\n $ gcloud config set project PROJECT_ID\n'.format(
account=account, project=properties.VALUES.core.project.Get()))
return creds
def _UpdateADC(creds, add_quota_project_to_adc):
"""Updates the ADC json with the credentials creds."""
old_adc_json = command_auth_util.GetADCAsJson()
command_auth_util.WriteGcloudCredentialsToADC(creds, add_quota_project_to_adc)
new_adc_json = command_auth_util.GetADCAsJson()
if new_adc_json and new_adc_json != old_adc_json:
adc_msg = '\nApplication default credentials (ADC) were updated.'
quota_project = command_auth_util.GetQuotaProjectFromADC()
if quota_project:
adc_msg = adc_msg + (
"\n'{}' is added to ADC as the quota project.\nTo "
'just update the quota project in ADC, use $gcloud auth '
'application-default set-quota-project.'.format(quota_project))
log.status.Print(adc_msg)
def _ValidateADCFlags(update_adc, add_quota_project_to_adc):
if not update_adc and add_quota_project_to_adc:
raise calliope_exceptions.InvalidArgumentException(
'--add-quota-project-to-adc',
'--add-quota-project-to-adc cannot be specified without specifying '
'--update-adc.'
)