Iam.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. <?php
  2. /*
  3. * Copyright 2019 Google LLC
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. namespace Google\Auth;
  18. use Google\Auth\HttpHandler\HttpClientCache;
  19. use Google\Auth\HttpHandler\HttpHandlerFactory;
  20. use GuzzleHttp\Psr7;
  21. use GuzzleHttp\Psr7\Utils;
  22. /**
  23. * Tools for using the IAM API.
  24. *
  25. * @see https://cloud.google.com/iam/docs IAM Documentation
  26. */
  27. class Iam
  28. {
  29. /**
  30. * @deprecated
  31. */
  32. const IAM_API_ROOT = 'https://iamcredentials.googleapis.com/v1';
  33. const SIGN_BLOB_PATH = '%s:signBlob?alt=json';
  34. const SERVICE_ACCOUNT_NAME = 'projects/-/serviceAccounts/%s';
  35. private const IAM_API_ROOT_TEMPLATE = 'https://iamcredentials.UNIVERSE_DOMAIN/v1';
  36. /**
  37. * @var callable
  38. */
  39. private $httpHandler;
  40. private string $universeDomain;
  41. /**
  42. * @param callable $httpHandler [optional] The HTTP Handler to send requests.
  43. */
  44. public function __construct(
  45. callable $httpHandler = null,
  46. string $universeDomain = GetUniverseDomainInterface::DEFAULT_UNIVERSE_DOMAIN
  47. ) {
  48. $this->httpHandler = $httpHandler
  49. ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
  50. $this->universeDomain = $universeDomain;
  51. }
  52. /**
  53. * Sign a string using the IAM signBlob API.
  54. *
  55. * Note that signing using IAM requires your service account to have the
  56. * `iam.serviceAccounts.signBlob` permission, part of the "Service Account
  57. * Token Creator" IAM role.
  58. *
  59. * @param string $email The service account email.
  60. * @param string $accessToken An access token from the service account.
  61. * @param string $stringToSign The string to be signed.
  62. * @param array<string> $delegates [optional] A list of service account emails to
  63. * add to the delegate chain. If omitted, the value of `$email` will
  64. * be used.
  65. * @return string The signed string, base64-encoded.
  66. */
  67. public function signBlob($email, $accessToken, $stringToSign, array $delegates = [])
  68. {
  69. $httpHandler = $this->httpHandler;
  70. $name = sprintf(self::SERVICE_ACCOUNT_NAME, $email);
  71. $apiRoot = str_replace('UNIVERSE_DOMAIN', $this->universeDomain, self::IAM_API_ROOT_TEMPLATE);
  72. $uri = $apiRoot . '/' . sprintf(self::SIGN_BLOB_PATH, $name);
  73. if ($delegates) {
  74. foreach ($delegates as &$delegate) {
  75. $delegate = sprintf(self::SERVICE_ACCOUNT_NAME, $delegate);
  76. }
  77. } else {
  78. $delegates = [$name];
  79. }
  80. $body = [
  81. 'delegates' => $delegates,
  82. 'payload' => base64_encode($stringToSign),
  83. ];
  84. $headers = [
  85. 'Authorization' => 'Bearer ' . $accessToken
  86. ];
  87. $request = new Psr7\Request(
  88. 'POST',
  89. $uri,
  90. $headers,
  91. Utils::streamFor(json_encode($body))
  92. );
  93. $res = $httpHandler($request);
  94. $body = json_decode((string) $res->getBody(), true);
  95. return $body['signedBlob'];
  96. }
  97. }