blob: 277f4b7f36bf5da02a7ef6b8b9d63ccfdcf4a92f [file] [log] [blame]
C.J. Collier37141e42020-02-13 13:49:49 -08001# Copyright 2017 Google LLC
Jon Wayne Parrott924191c2017-02-15 16:43:23 -08002#
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 at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# 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 and
13# 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 base64
Tres Seaver560cf1e2021-08-03 16:35:54 -040023import http.client
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080024import json
25
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080026from google.auth import _helpers
Jon Wayne Parrott254befe2017-02-22 14:37:31 -080027from google.auth import crypt
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080028from google.auth import exceptions
29
Bu Sun Kim694d83f2020-09-08 15:28:08 -060030_IAM_API_ROOT_URI = "https://iamcredentials.googleapis.com/v1"
Bu Sun Kim9eec0912019-10-21 17:04:21 -070031_SIGN_BLOB_URI = _IAM_API_ROOT_URI + "/projects/-/serviceAccounts/{}:signBlob?alt=json"
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080032
33
Jon Wayne Parrott254befe2017-02-22 14:37:31 -080034class Signer(crypt.Signer):
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080035 """Signs messages using the IAM `signBlob API`_.
36
37 This is useful when you need to sign bytes but do not have access to the
38 credential's private key file.
39
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080040 .. _signBlob API:
41 https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts
42 /signBlob
43 """
44
45 def __init__(self, request, credentials, service_account_email):
46 """
47 Args:
48 request (google.auth.transport.Request): The object used to make
49 HTTP requests.
50 credentials (google.auth.credentials.Credentials): The credentials
51 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/iam
55 - https://www.googleapis.com/auth/cloud-platform
56 service_account_email (str): The service account email identifying
57 which service account to use to sign bytes. Often, this can
58 be the same as the service account email in the given
59 credentials.
60 """
61 self._request = request
62 self._credentials = credentials
63 self._service_account_email = service_account_email
64
65 def _make_signing_request(self, message):
66 """Makes a request to the API signBlob API."""
67 message = _helpers.to_bytes(message)
68
Bu Sun Kim9eec0912019-10-21 17:04:21 -070069 method = "POST"
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080070 url = _SIGN_BLOB_URI.format(self._service_account_email)
Kenji Imamula20f82e22020-07-31 05:40:02 +090071 headers = {"Content-Type": "application/json"}
Bu Sun Kima57a7702020-01-10 13:17:34 -080072 body = json.dumps(
Bu Sun Kim694d83f2020-09-08 15:28:08 -060073 {"payload": base64.b64encode(message).decode("utf-8")}
Bu Sun Kima57a7702020-01-10 13:17:34 -080074 ).encode("utf-8")
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080075
76 self._credentials.before_request(self._request, method, url, headers)
Bu Sun Kim9eec0912019-10-21 17:04:21 -070077 response = self._request(url=url, method=method, body=body, headers=headers)
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080078
Tres Seaver560cf1e2021-08-03 16:35:54 -040079 if response.status != http.client.OK:
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080080 raise exceptions.TransportError(
Aarni Koskelae9ca25f2021-05-18 18:08:05 +030081 "Error calling the IAM signBlob API: {}".format(response.data)
Bu Sun Kim9eec0912019-10-21 17:04:21 -070082 )
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080083
Bu Sun Kim9eec0912019-10-21 17:04:21 -070084 return json.loads(response.data.decode("utf-8"))
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080085
86 @property
87 def key_id(self):
88 """Optional[str]: The key ID used to identify this private key.
89
Jon Wayne Parrott254befe2017-02-22 14:37:31 -080090 .. warning::
91 This is always ``None``. The key ID used by IAM can not
92 be reliably determined ahead of time.
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080093 """
Jon Wayne Parrott254befe2017-02-22 14:37:31 -080094 return None
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080095
Jon Wayne Parrott254befe2017-02-22 14:37:31 -080096 @_helpers.copy_docstring(crypt.Signer)
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080097 def sign(self, message):
Jon Wayne Parrott924191c2017-02-15 16:43:23 -080098 response = self._make_signing_request(message)
Bu Sun Kim694d83f2020-09-08 15:28:08 -060099 return base64.b64decode(response["signedBlob"])