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\ApplicationDefaultCredentials;
21use Google\Auth\Credentials\GCECredentials;
22use Google\Auth\Credentials\ServiceAccountCredentials;
23use GuzzleHttp\Psr7;
24use PHPUnit\Framework\TestCase;
25
26class ADCGetTest extends TestCase
27{
28    private $originalHome;
29
30    protected function setUp()
31    {
32        $this->originalHome = getenv('HOME');
33    }
34
35    protected function tearDown()
36    {
37        if ($this->originalHome != getenv('HOME')) {
38            putenv('HOME=' . $this->originalHome);
39        }
40        putenv(ServiceAccountCredentials::ENV_VAR);  // removes it from
41    }
42
43    /**
44     * @expectedException DomainException
45     */
46    public function testIsFailsEnvSpecifiesNonExistentFile()
47    {
48        $keyFile = __DIR__ . '/fixtures' . '/does-not-exist-private.json';
49        putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile);
50        ApplicationDefaultCredentials::getCredentials('a scope');
51    }
52
53    public function testLoadsOKIfEnvSpecifiedIsValid()
54    {
55        $keyFile = __DIR__ . '/fixtures' . '/private.json';
56        putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile);
57        $this->assertNotNull(
58            ApplicationDefaultCredentials::getCredentials('a scope')
59        );
60    }
61
62    public function testLoadsDefaultFileIfPresentAndEnvVarIsNotSet()
63    {
64        putenv('HOME=' . __DIR__ . '/fixtures');
65        $this->assertNotNull(
66            ApplicationDefaultCredentials::getCredentials('a scope')
67        );
68    }
69
70    /**
71     * @expectedException DomainException
72     */
73    public function testFailsIfNotOnGceAndNoDefaultFileFound()
74    {
75        putenv('HOME=' . __DIR__ . '/not_exist_fixtures');
76        // simulate not being GCE and retry attempts by returning multiple 500s
77        $httpHandler = getHandler([
78            buildResponse(500),
79            buildResponse(500),
80            buildResponse(500)
81        ]);
82
83        ApplicationDefaultCredentials::getCredentials('a scope', $httpHandler);
84    }
85
86    public function testSuccedsIfNoDefaultFilesButIsOnGCE()
87    {
88        $wantedTokens = [
89            'access_token' => '1/abdef1234567890',
90            'expires_in' => '57',
91            'token_type' => 'Bearer',
92        ];
93        $jsonTokens = json_encode($wantedTokens);
94
95        // simulate the response from GCE.
96        $httpHandler = getHandler([
97            buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']),
98            buildResponse(200, [], Psr7\stream_for($jsonTokens)),
99        ]);
100
101        $this->assertNotNull(
102            ApplicationDefaultCredentials::getCredentials('a scope', $httpHandler)
103        );
104    }
105}
106
107class ADCGetMiddlewareTest extends TestCase
108{
109    private $originalHome;
110
111    protected function setUp()
112    {
113        $this->originalHome = getenv('HOME');
114    }
115
116    protected function tearDown()
117    {
118        if ($this->originalHome != getenv('HOME')) {
119            putenv('HOME=' . $this->originalHome);
120        }
121        putenv(ServiceAccountCredentials::ENV_VAR);  // removes it if assigned
122    }
123
124    /**
125     * @expectedException DomainException
126     */
127    public function testIsFailsEnvSpecifiesNonExistentFile()
128    {
129        $keyFile = __DIR__ . '/fixtures' . '/does-not-exist-private.json';
130        putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile);
131        ApplicationDefaultCredentials::getMiddleware('a scope');
132    }
133
134    public function testLoadsOKIfEnvSpecifiedIsValid()
135    {
136        $keyFile = __DIR__ . '/fixtures' . '/private.json';
137        putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile);
138        $this->assertNotNull(ApplicationDefaultCredentials::getMiddleware('a scope'));
139    }
140
141    public function testLoadsDefaultFileIfPresentAndEnvVarIsNotSet()
142    {
143        putenv('HOME=' . __DIR__ . '/fixtures');
144        $this->assertNotNull(ApplicationDefaultCredentials::getMiddleware('a scope'));
145    }
146
147    /**
148     * @expectedException DomainException
149     */
150    public function testFailsIfNotOnGceAndNoDefaultFileFound()
151    {
152        putenv('HOME=' . __DIR__ . '/not_exist_fixtures');
153
154        // simulate not being GCE and retry attempts by returning multiple 500s
155        $httpHandler = getHandler([
156            buildResponse(500),
157            buildResponse(500),
158            buildResponse(500)
159        ]);
160
161        ApplicationDefaultCredentials::getMiddleware('a scope', $httpHandler);
162    }
163
164    public function testWithCacheOptions()
165    {
166        $keyFile = __DIR__ . '/fixtures' . '/private.json';
167        putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile);
168
169        $httpHandler = getHandler([
170            buildResponse(200),
171        ]);
172
173        $cacheOptions = [];
174        $cachePool = $this->prophesize('Psr\Cache\CacheItemPoolInterface');
175
176        $middleware = ApplicationDefaultCredentials::getMiddleware(
177            'a scope',
178            $httpHandler,
179            $cacheOptions,
180            $cachePool->reveal()
181        );
182    }
183
184    public function testSuccedsIfNoDefaultFilesButIsOnGCE()
185    {
186        $wantedTokens = [
187            'access_token' => '1/abdef1234567890',
188            'expires_in' => '57',
189            'token_type' => 'Bearer',
190        ];
191        $jsonTokens = json_encode($wantedTokens);
192
193        // simulate the response from GCE.
194        $httpHandler = getHandler([
195            buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']),
196            buildResponse(200, [], Psr7\stream_for($jsonTokens)),
197        ]);
198
199        $this->assertNotNull(ApplicationDefaultCredentials::getMiddleware('a scope', $httpHandler));
200    }
201}
202
203class ADCGetCredentialsAppEngineTest extends BaseTest
204{
205    private $originalHome;
206    private $originalServiceAccount;
207
208    protected function setUp()
209    {
210        // set home to be somewhere else
211        $this->originalHome = getenv('HOME');
212        putenv('HOME=' . __DIR__ . '/not_exist_fixtures');
213
214        // remove service account path
215        $this->originalServiceAccount = getenv(ServiceAccountCredentials::ENV_VAR);
216        putenv(ServiceAccountCredentials::ENV_VAR);
217    }
218
219    protected function tearDown()
220    {
221        // removes it if assigned
222        putenv('HOME=' . $this->originalHome);
223        putenv(ServiceAccountCredentials::ENV_VAR . '=' . $this->originalServiceAccount);
224        putenv('GAE_INSTANCE');
225    }
226
227    public function testAppEngineStandard()
228    {
229        $_SERVER['SERVER_SOFTWARE'] = 'Google App Engine';
230        $this->assertInstanceOf(
231            'Google\Auth\Credentials\AppIdentityCredentials',
232            ApplicationDefaultCredentials::getCredentials()
233        );
234    }
235
236    public function testAppEngineFlexible()
237    {
238        $_SERVER['SERVER_SOFTWARE'] = 'Google App Engine';
239        putenv('GAE_INSTANCE=aef-default-20180313t154438');
240        $httpHandler = getHandler([
241            buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']),
242        ]);
243        $this->assertInstanceOf(
244            'Google\Auth\Credentials\GCECredentials',
245            ApplicationDefaultCredentials::getCredentials(null, $httpHandler)
246        );
247    }
248}
249
250// @todo consider a way to DRY this and above class up
251class ADCGetSubscriberTest extends BaseTest
252{
253    private $originalHome;
254
255    protected function setUp()
256    {
257        $this->onlyGuzzle5();
258
259        $this->originalHome = getenv('HOME');
260    }
261
262    protected function tearDown()
263    {
264        if ($this->originalHome != getenv('HOME')) {
265            putenv('HOME=' . $this->originalHome);
266        }
267        putenv(ServiceAccountCredentials::ENV_VAR);  // removes it if assigned
268    }
269
270    /**
271     * @expectedException DomainException
272     */
273    public function testIsFailsEnvSpecifiesNonExistentFile()
274    {
275        $keyFile = __DIR__ . '/fixtures' . '/does-not-exist-private.json';
276        putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile);
277        ApplicationDefaultCredentials::getSubscriber('a scope');
278    }
279
280    public function testLoadsOKIfEnvSpecifiedIsValid()
281    {
282        $keyFile = __DIR__ . '/fixtures' . '/private.json';
283        putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile);
284        $this->assertNotNull(ApplicationDefaultCredentials::getSubscriber('a scope'));
285    }
286
287    public function testLoadsDefaultFileIfPresentAndEnvVarIsNotSet()
288    {
289        putenv('HOME=' . __DIR__ . '/fixtures');
290        $this->assertNotNull(ApplicationDefaultCredentials::getSubscriber('a scope'));
291    }
292
293    /**
294     * @expectedException DomainException
295     */
296    public function testFailsIfNotOnGceAndNoDefaultFileFound()
297    {
298        putenv('HOME=' . __DIR__ . '/not_exist_fixtures');
299
300        // simulate not being GCE by return 500
301        $httpHandler = getHandler([
302            buildResponse(500),
303        ]);
304
305        ApplicationDefaultCredentials::getSubscriber('a scope', $httpHandler);
306    }
307
308    public function testWithCacheOptions()
309    {
310        $keyFile = __DIR__ . '/fixtures' . '/private.json';
311        putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile);
312
313        $httpHandler = getHandler([
314            buildResponse(200),
315        ]);
316
317        $cacheOptions = [];
318        $cachePool = $this->getMock('Psr\Cache\CacheItemPoolInterface');
319
320        $subscriber = ApplicationDefaultCredentials::getSubscriber(
321            'a scope',
322            $httpHandler,
323            $cacheOptions,
324            $cachePool
325        );
326    }
327
328    public function testSuccedsIfNoDefaultFilesButIsOnGCE()
329    {
330        $wantedTokens = [
331            'access_token' => '1/abdef1234567890',
332            'expires_in' => '57',
333            'token_type' => 'Bearer',
334        ];
335        $jsonTokens = json_encode($wantedTokens);
336
337        // simulate the response from GCE.
338        $httpHandler = getHandler([
339            buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']),
340            buildResponse(200, [], Psr7\stream_for($jsonTokens)),
341        ]);
342
343        $this->assertNotNull(ApplicationDefaultCredentials::getSubscriber('a scope', $httpHandler));
344    }
345}
346