codekingpro/portable-devtools
114k
1# Copyright 2017 Google LLC2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7# http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14 15"""Tools for using the Google `Cloud Identity and Access Management (IAM)16API`_'s auth-related functionality.17 18.. _Cloud Identity and Access Management (IAM) API:19 https://cloud.google.com/iam/docs/20"""21 22import base6423import http.client as http_client24import json25 26from google.auth import _helpers27from google.auth import crypt28from google.auth import exceptions29 30_IAM_API_ROOT_URI = "https://iamcredentials.googleapis.com/v1"31_SIGN_BLOB_URI = _IAM_API_ROOT_URI + "/projects/-/serviceAccounts/{}:signBlob?alt=json"32 33 34class Signer(crypt.Signer):35 """Signs messages using the IAM `signBlob API`_.36 37 This is useful when you need to sign bytes but do not have access to the38 credential's private key file.39 40 .. _signBlob API:41 https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts42 /signBlob43 """44 45 def __init__(self, request, credentials, service_account_email):46 """47 Args:48 request (google.auth.transport.Request): The object used to make49 HTTP requests.50 credentials (google.auth.credentials.Credentials): The credentials51 that will be used to authenticate the request to the IAM API.52 The credentials must have of one the following scopes:53 54 - https://www.googleapis.com/auth/iam55 - https://www.googleapis.com/auth/cloud-platform56 service_account_email (str): The service account email identifying57 which service account to use to sign bytes. Often, this can58 be the same as the service account email in the given59 credentials.60 """61 self._request = request62 self._credentials = credentials63 self._service_account_email = service_account_email64 65 def _make_signing_request(self, message):66 """Makes a request to the API signBlob API."""67 message = _helpers.to_bytes(message)68 69 method = "POST"70 url = _SIGN_BLOB_URI.format(self._service_account_email)71 headers = {"Content-Type": "application/json"}72 body = json.dumps(73 {"payload": base64.b64encode(message).decode("utf-8")}74 ).encode("utf-8")75 76 self._credentials.before_request(self._request, method, url, headers)77 response = self._request(url=url, method=method, body=body, headers=headers)78 79 if response.status != http_client.OK:80 raise exceptions.TransportError(81 "Error calling the IAM signBlob API: {}".format(response.data)82 )83 84 return json.loads(response.data.decode("utf-8"))85 86 @property87 def key_id(self):88 """Optional[str]: The key ID used to identify this private key.89 90 .. warning::91 This is always ``None``. The key ID used by IAM can not92 be reliably determined ahead of time.93 """94 return None95 96 @_helpers.copy_docstring(crypt.Signer)97 def sign(self, message):98 response = self._make_signing_request(message)99 return base64.b64decode(response["signedBlob"])100 