1<?php 2/* 3 * Copyright 2015 Google Inc. 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 18namespace Google\Auth\Tests; 19 20use Google\Auth\Credentials\GCECredentials; 21use Google\Auth\HttpHandler\HttpClientCache; 22use GuzzleHttp\ClientInterface; 23use GuzzleHttp\Psr7; 24use PHPUnit\Framework\TestCase; 25use Prophecy\Argument; 26 27/** 28 * @group credentials 29 * @group credentials-gce 30 */ 31class GCECredentialsTest extends TestCase 32{ 33 public function testOnGCEIsFalseOnClientErrorStatus() 34 { 35 // simulate retry attempts by returning multiple 400s 36 $httpHandler = getHandler([ 37 buildResponse(400), 38 buildResponse(400), 39 buildResponse(400) 40 ]); 41 $this->assertFalse(GCECredentials::onGCE($httpHandler)); 42 } 43 44 public function testOnGCEIsFalseOnServerErrorStatus() 45 { 46 // simulate retry attempts by returning multiple 500s 47 $httpHandler = getHandler([ 48 buildResponse(500), 49 buildResponse(500), 50 buildResponse(500) 51 ]); 52 $this->assertFalse(GCECredentials::onGCE($httpHandler)); 53 } 54 55 public function testOnGCEIsFalseOnOkStatusWithoutExpectedHeader() 56 { 57 $httpHandler = getHandler([ 58 buildResponse(200), 59 ]); 60 $this->assertFalse(GCECredentials::onGCE($httpHandler)); 61 } 62 63 public function testOnGCEIsOkIfGoogleIsTheFlavor() 64 { 65 $httpHandler = getHandler([ 66 buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']), 67 ]); 68 $this->assertTrue(GCECredentials::onGCE($httpHandler)); 69 } 70 71 public function testOnAppEngineFlexIsFalseByDefault() 72 { 73 $this->assertFalse(GCECredentials::onAppEngineFlexible()); 74 } 75 76 public function testOnAppEngineFlexIsTrueWhenGaeInstanceHasAefPrefix() 77 { 78 putenv('GAE_INSTANCE=aef-default-20180313t154438'); 79 $this->assertTrue(GCECredentials::onAppEngineFlexible()); 80 putenv('GAE_INSTANCE'); 81 } 82 83 public function testGetCacheKeyShouldNotBeEmpty() 84 { 85 $g = new GCECredentials(); 86 $this->assertNotEmpty($g->getCacheKey()); 87 } 88 89 public function testFetchAuthTokenShouldBeEmptyIfNotOnGCE() 90 { 91 // simulate retry attempts by returning multiple 500s 92 $httpHandler = getHandler([ 93 buildResponse(500), 94 buildResponse(500), 95 buildResponse(500) 96 ]); 97 $g = new GCECredentials(); 98 $this->assertEquals(array(), $g->fetchAuthToken($httpHandler)); 99 } 100 101 /** 102 * @expectedException Exception 103 * @expectedExceptionMessage Invalid JSON response 104 */ 105 public function testFetchAuthTokenShouldFailIfResponseIsNotJson() 106 { 107 $notJson = '{"foo": , this is cannot be passed as json" "bar"}'; 108 $httpHandler = getHandler([ 109 buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']), 110 buildResponse(200, [], $notJson), 111 ]); 112 $g = new GCECredentials(); 113 $g->fetchAuthToken($httpHandler); 114 } 115 116 public function testFetchAuthTokenShouldReturnTokenInfo() 117 { 118 $wantedTokens = [ 119 'access_token' => '1/abdef1234567890', 120 'expires_in' => '57', 121 'token_type' => 'Bearer', 122 ]; 123 $jsonTokens = json_encode($wantedTokens); 124 $httpHandler = getHandler([ 125 buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']), 126 buildResponse(200, [], Psr7\stream_for($jsonTokens)), 127 ]); 128 $g = new GCECredentials(); 129 $this->assertEquals($wantedTokens, $g->fetchAuthToken($httpHandler)); 130 $this->assertEquals(time() + 57, $g->getLastReceivedToken()['expires_at']); 131 } 132 133 public function testGetLastReceivedTokenIsNullByDefault() 134 { 135 $creds = new GCECredentials; 136 $this->assertNull($creds->getLastReceivedToken()); 137 } 138 139 public function testGetClientName() 140 { 141 $expected = 'foobar'; 142 143 $httpHandler = getHandler([ 144 buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']), 145 buildResponse(200, [], Psr7\stream_for($expected)), 146 buildResponse(200, [], Psr7\stream_for('notexpected')) 147 ]); 148 149 $creds = new GCECredentials; 150 $this->assertEquals($expected, $creds->getClientName($httpHandler)); 151 152 // call again to test cached value 153 $this->assertEquals($expected, $creds->getClientName($httpHandler)); 154 } 155 156 public function testGetClientNameShouldBeEmptyIfNotOnGCE() 157 { 158 // simulate retry attempts by returning multiple 500s 159 $httpHandler = getHandler([ 160 buildResponse(500), 161 buildResponse(500), 162 buildResponse(500) 163 ]); 164 165 $creds = new GCECredentials; 166 $this->assertEquals('', $creds->getClientName($httpHandler)); 167 } 168 169 public function testSignBlob() 170 { 171 $guzzleVersion = ClientInterface::VERSION; 172 if ($guzzleVersion[0] === '5') { 173 $this->markTestSkipped('Only compatible with guzzle 6+'); 174 } 175 176 $expectedEmail = 'test@test.com'; 177 $expectedAccessToken = 'token'; 178 $stringToSign = 'inputString'; 179 $resultString = 'foobar'; 180 $token = [ 181 'access_token' => $expectedAccessToken, 182 'expires_in' => '57', 183 'token_type' => 'Bearer', 184 ]; 185 186 $iam = $this->prophesize('Google\Auth\Iam'); 187 $iam->signBlob($expectedEmail, $expectedAccessToken, $stringToSign) 188 ->shouldBeCalled() 189 ->willReturn($resultString); 190 191 $client = $this->prophesize('GuzzleHttp\ClientInterface'); 192 $client->send(Argument::any(), Argument::any()) 193 ->willReturn( 194 buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']), 195 buildResponse(200, [], Psr7\stream_for($expectedEmail)), 196 buildResponse(200, [], Psr7\stream_for(json_encode($token))) 197 ); 198 199 HttpClientCache::setHttpClient($client->reveal()); 200 201 $creds = new GCECredentials($iam->reveal()); 202 $signature = $creds->signBlob($stringToSign); 203 } 204 205 public function testSignBlobWithLastReceivedAccessToken() 206 { 207 $guzzleVersion = ClientInterface::VERSION; 208 if ($guzzleVersion[0] === '5') { 209 $this->markTestSkipped('Only compatible with guzzle 6+'); 210 } 211 212 $expectedEmail = 'test@test.com'; 213 $expectedAccessToken = 'token'; 214 $notExpectedAccessToken = 'othertoken'; 215 $stringToSign = 'inputString'; 216 $resultString = 'foobar'; 217 $token1 = [ 218 'access_token' => $expectedAccessToken, 219 'expires_in' => '57', 220 'token_type' => 'Bearer', 221 ]; 222 $token2 = [ 223 'access_token' => $notExpectedAccessToken, 224 'expires_in' => '57', 225 'token_type' => 'Bearer', 226 ]; 227 228 $iam = $this->prophesize('Google\Auth\Iam'); 229 $iam->signBlob($expectedEmail, $expectedAccessToken, $stringToSign) 230 ->shouldBeCalled() 231 ->willReturn($resultString); 232 233 $client = $this->prophesize('GuzzleHttp\ClientInterface'); 234 $client->send(Argument::any(), Argument::any()) 235 ->willReturn( 236 buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']), 237 buildResponse(200, [], Psr7\stream_for(json_encode($token1))), 238 buildResponse(200, [], Psr7\stream_for($expectedEmail)), 239 buildResponse(200, [], Psr7\stream_for(json_encode($token2))) 240 ); 241 242 HttpClientCache::setHttpClient($client->reveal()); 243 244 $creds = new GCECredentials($iam->reveal()); 245 // cache a token 246 $creds->fetchAuthToken(); 247 248 $signature = $creds->signBlob($stringToSign); 249 } 250} 251