Iam.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. const IAM_API_ROOT = 'https://iamcredentials.googleapis.com/v1';
  30. const SIGN_BLOB_PATH = '%s:signBlob?alt=json';
  31. const SERVICE_ACCOUNT_NAME = 'projects/-/serviceAccounts/%s';
  32. /**
  33. * @var callable
  34. */
  35. private $httpHandler;
  36. /**
  37. * @param callable $httpHandler [optional] The HTTP Handler to send requests.
  38. */
  39. public function __construct(callable $httpHandler = null)
  40. {
  41. $this->httpHandler = $httpHandler
  42. ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
  43. }
  44. /**
  45. * Sign a string using the IAM signBlob API.
  46. *
  47. * Note that signing using IAM requires your service account to have the
  48. * `iam.serviceAccounts.signBlob` permission, part of the "Service Account
  49. * Token Creator" IAM role.
  50. *
  51. * @param string $email The service account email.
  52. * @param string $accessToken An access token from the service account.
  53. * @param string $stringToSign The string to be signed.
  54. * @param array<string> $delegates [optional] A list of service account emails to
  55. * add to the delegate chain. If omitted, the value of `$email` will
  56. * be used.
  57. * @return string The signed string, base64-encoded.
  58. */
  59. public function signBlob($email, $accessToken, $stringToSign, array $delegates = [])
  60. {
  61. $httpHandler = $this->httpHandler;
  62. $name = sprintf(self::SERVICE_ACCOUNT_NAME, $email);
  63. $uri = self::IAM_API_ROOT . '/' . sprintf(self::SIGN_BLOB_PATH, $name);
  64. if ($delegates) {
  65. foreach ($delegates as &$delegate) {
  66. $delegate = sprintf(self::SERVICE_ACCOUNT_NAME, $delegate);
  67. }
  68. } else {
  69. $delegates = [$name];
  70. }
  71. $body = [
  72. 'delegates' => $delegates,
  73. 'payload' => base64_encode($stringToSign),
  74. ];
  75. $headers = [
  76. 'Authorization' => 'Bearer ' . $accessToken
  77. ];
  78. $request = new Psr7\Request(
  79. 'POST',
  80. $uri,
  81. $headers,
  82. Utils::streamFor(json_encode($body))
  83. );
  84. $res = $httpHandler($request);
  85. $body = json_decode((string) $res->getBody(), true);
  86. return $body['signedBlob'];
  87. }
  88. }