124 lines
4.5 KiB
Python
124 lines
4.5 KiB
Python
# -*- coding: utf-8 -*- #
|
|
# Copyright 2016 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.
|
|
"""Manages logic for service accounts."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import unicode_literals
|
|
|
|
import json
|
|
|
|
from googlecloudsdk.core import config
|
|
from googlecloudsdk.core import exceptions
|
|
from googlecloudsdk.core.credentials import creds as c_creds
|
|
from googlecloudsdk.core.credentials import p12_service_account
|
|
from googlecloudsdk.core.util import files
|
|
|
|
from oauth2client import service_account
|
|
|
|
_SERVICE_ACCOUNT_TYPE = 'service_account'
|
|
|
|
|
|
class Error(exceptions.Error):
|
|
"""Errors raised by this module."""
|
|
|
|
|
|
class UnsupportedCredentialsType(Error):
|
|
"""Raised when given type credentials cannot be created."""
|
|
|
|
|
|
class BadCredentialFileException(Error):
|
|
"""Raised when file cannot be read."""
|
|
|
|
|
|
class BadCredentialJsonFileException(Error):
|
|
"""Raised when file cannot be read."""
|
|
|
|
|
|
def IsServiceAccountConfig(content_json):
|
|
"""Returns whether a JSON content corresponds to an service account cred."""
|
|
return (content_json or {}).get('type') == _SERVICE_ACCOUNT_TYPE
|
|
|
|
|
|
def CredentialsFromAdcFile(filename):
|
|
"""Load credentials from given service account json file."""
|
|
content = files.ReadFileContents(filename)
|
|
try:
|
|
json_key = json.loads(content)
|
|
return CredentialsFromAdcDict(json_key)
|
|
except ValueError as e:
|
|
raise BadCredentialFileException('Could not read json file {0}: {1}'.format(
|
|
filename, e))
|
|
|
|
|
|
def CredentialsFromAdcDict(json_key):
|
|
"""Creates oauth2client creds from a dict of application default creds."""
|
|
if 'client_email' not in json_key:
|
|
raise BadCredentialJsonFileException(
|
|
'The .json key file is not in a valid format.')
|
|
|
|
json_key['token_uri'] = c_creds.GetEffectiveTokenUriFromCreds(json_key)
|
|
|
|
creds = service_account.ServiceAccountCredentials.from_json_keyfile_dict(
|
|
json_key, scopes=config.CLOUDSDK_SCOPES)
|
|
# User agent needs to be set separately, see
|
|
# https://github.com/google/oauth2client/issues/445
|
|
# pylint: disable=protected-access
|
|
creds.user_agent = creds._user_agent = config.CLOUDSDK_USER_AGENT
|
|
return creds
|
|
|
|
|
|
def CredentialsFromAdcDictGoogleAuth(json_key):
|
|
"""Creates google-auth creds from a dict of application default creds."""
|
|
# Import only when necessary to decrease the startup time. Move it to
|
|
# global once google-auth is ready to replace oauth2client.
|
|
# pylint: disable=g-import-not-at-top
|
|
from google.oauth2 import service_account as google_auth_service_account
|
|
# pylint: enable=g-import-not-at-top
|
|
|
|
if 'client_email' not in json_key:
|
|
raise BadCredentialJsonFileException(
|
|
'The .json key file is not in a valid format.')
|
|
|
|
# 'token_uri' is required by google-auth credentails construction. However,
|
|
# the service account keys generated before 2015 do not provide this field.
|
|
# More details in http://shortn/_LtMjDvpgfh.
|
|
json_key['token_uri'] = c_creds.GetEffectiveTokenUriFromCreds(json_key)
|
|
|
|
service_account_credentials = (
|
|
google_auth_service_account.Credentials.from_service_account_info)
|
|
creds = service_account_credentials(json_key, scopes=config.CLOUDSDK_SCOPES)
|
|
# The below additional fields are not natively supported in the google-auth
|
|
# library but are needed in gcloud:
|
|
# private_key, private_key_id: required by credentials deserialization;
|
|
# client_id: to provid backward compatibility for oauth2client. This field is
|
|
# used in oauth2client service account credentials.
|
|
creds.private_key = json_key.get('private_key')
|
|
creds.private_key_id = json_key.get('private_key_id')
|
|
creds.client_id = json_key.get('client_id')
|
|
return creds
|
|
|
|
|
|
def CredentialsFromP12Key(private_key, account, password=None):
|
|
"""Creates credentials object from given p12 private key and account name."""
|
|
|
|
return p12_service_account.CreateP12ServiceAccount(
|
|
private_key,
|
|
password,
|
|
service_account_email=account,
|
|
token_uri=c_creds.GetEffectiveTokenUriFromCreds({}),
|
|
scopes=config.CLOUDSDK_SCOPES,
|
|
)
|