diff --git a/src/Credentials/ExternalAccountCredentials.php b/src/Credentials/ExternalAccountCredentials.php index bc4a68610..c3a8c628a 100644 --- a/src/Credentials/ExternalAccountCredentials.php +++ b/src/Credentials/ExternalAccountCredentials.php @@ -43,7 +43,7 @@ class ExternalAccountCredentials implements use UpdateMetadataTrait; private const EXTERNAL_ACCOUNT_TYPE = 'external_account'; - private const CLOUD_RESOURCE_MANAGER_URL='https://cloudresourcemanager.UNIVERSE_DOMAIN/v1/projects/%s'; + private const CLOUD_RESOURCE_MANAGER_URL = 'https://cloudresourcemanager.UNIVERSE_DOMAIN/v1/projects/%s'; private OAuth2 $auth; private ?string $quotaProject; diff --git a/src/Iam.php b/src/Iam.php index 943ecf2d6..2f67f0009 100644 --- a/src/Iam.php +++ b/src/Iam.php @@ -29,22 +29,31 @@ */ class Iam { + /** + * @deprecated + */ const IAM_API_ROOT = 'https://iamcredentials.googleapis.com/v1'; const SIGN_BLOB_PATH = '%s:signBlob?alt=json'; const SERVICE_ACCOUNT_NAME = 'projects/-/serviceAccounts/%s'; + private const IAM_API_ROOT_TEMPLATE = 'https://iamcredentials.UNIVERSE_DOMAIN/v1'; /** * @var callable */ private $httpHandler; + private string $universeDomain; + /** * @param callable $httpHandler [optional] The HTTP Handler to send requests. */ - public function __construct(callable $httpHandler = null) - { + public function __construct( + callable $httpHandler = null, + string $universeDomain = GetUniverseDomainInterface::DEFAULT_UNIVERSE_DOMAIN + ) { $this->httpHandler = $httpHandler ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient()); + $this->universeDomain = $universeDomain; } /** @@ -66,7 +75,8 @@ public function signBlob($email, $accessToken, $stringToSign, array $delegates = { $httpHandler = $this->httpHandler; $name = sprintf(self::SERVICE_ACCOUNT_NAME, $email); - $uri = self::IAM_API_ROOT . '/' . sprintf(self::SIGN_BLOB_PATH, $name); + $apiRoot = str_replace('UNIVERSE_DOMAIN', $this->universeDomain, self::IAM_API_ROOT_TEMPLATE); + $uri = $apiRoot . '/' . sprintf(self::SIGN_BLOB_PATH, $name); if ($delegates) { foreach ($delegates as &$delegate) { diff --git a/src/IamSignerTrait.php b/src/IamSignerTrait.php index 9de18b3fd..da3c90903 100644 --- a/src/IamSignerTrait.php +++ b/src/IamSignerTrait.php @@ -51,7 +51,12 @@ public function signBlob($stringToSign, $forceOpenSsl = false, $accessToken = nu // Providing a signer is useful for testing, but it's undocumented // because it's not something a user would generally need to do. - $signer = $this->iam ?: new Iam($httpHandler); + $signer = $this->iam; + if (!$signer) { + $signer = $this instanceof GetUniverseDomainInterface + ? new Iam($httpHandler, $this->getUniverseDomain()) + : new Iam($httpHandler); + } $email = $this->getClientName($httpHandler); diff --git a/tests/Credentials/GCECredentialsTest.php b/tests/Credentials/GCECredentialsTest.php index a82e6f5c9..5964b9a5c 100644 --- a/tests/Credentials/GCECredentialsTest.php +++ b/tests/Credentials/GCECredentialsTest.php @@ -23,6 +23,7 @@ use Google\Auth\Tests\BaseTest; use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Psr7; +use GuzzleHttp\Psr7\Request; use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Utils; use InvalidArgumentException; @@ -380,6 +381,44 @@ public function testSignBlobWithLastReceivedAccessToken() $signature = $creds->signBlob($stringToSign); } + public function testSignBlobWithUniverseDomain() + { + $token = [ + 'access_token' => 'token', + 'expires_in' => '57', + 'token_type' => 'Bearer', + ]; + $signedBlob = ['signedBlob' => 'abc123']; + $client = $this->prophesize('GuzzleHttp\ClientInterface'); + $client->send(Argument::any(), Argument::any()) + ->willReturn( + new Response(200, [], Utils::streamFor('test@test.com')), + new Response(200, [], Utils::streamFor(json_encode($token))) + ); + $client->send( + Argument::that( + fn (Request $request) => $request->getUri()->getHost() === 'iamcredentials.example-universe.com' + ), + Argument::any() + ) + ->shouldBeCalledOnce() + ->willReturn(new Response(200, [], Utils::streamFor(json_encode($signedBlob)))); + + HttpClientCache::setHttpClient($client->reveal()); + + $creds = new GCECredentials( + null, + null, + null, + null, + null, + 'example-universe.com' + ); + $creds->setIsOnGce(true); + $signature = $creds->signBlob('inputString'); + $this->assertEquals('abc123', $signature); + } + public function testGetProjectId() { $expected = 'foobar';