Skip to content

Commit a61a28d

Browse files
committed
Initial Compute Engine credentials for googleapis#457.
1 parent e89d061 commit a61a28d

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

src/Google/Auth/ComputeEngine.php

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<?php
2+
/*
3+
* Copyright 2014 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+
18+
require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
19+
20+
/**
21+
* Authentication via built-in Compute Engine service accounts.
22+
* The instance must be pre-configured with a service account
23+
* and the appropriate scopes.
24+
* @author Jonathan Parrott <[email protected]>
25+
*/
26+
class Google_Auth_ComputeEngine extends Google_Auth_Abstract
27+
{
28+
const METADATA_AUTH_URL = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/token';
29+
private $client;
30+
private $token;
31+
32+
public function __construct(Google_Client $client, $config = null)
33+
{
34+
$this->client = $client;
35+
}
36+
37+
/**
38+
* Perform an authenticated / signed apiHttpRequest.
39+
* This function takes the apiHttpRequest, calls apiAuth->sign on it
40+
* (which can modify the request in what ever way fits the auth mechanism)
41+
* and then calls apiCurlIO::makeRequest on the signed request
42+
*
43+
* @param Google_Http_Request $request
44+
* @return Google_Http_Request The resulting HTTP response including the
45+
* responseHttpCode, responseHeaders and responseBody.
46+
*/
47+
public function authenticatedRequest(Google_Http_Request $request)
48+
{
49+
$request = $this->sign($request);
50+
return $this->client->getIo()->makeRequest($request);
51+
}
52+
53+
/**
54+
* @param string $token
55+
* @throws Google_Auth_Exception
56+
*/
57+
public function setAccessToken($token)
58+
{
59+
$token = json_decode($token, true);
60+
if ($token == null) {
61+
throw new Google_Auth_Exception('Could not json decode the token');
62+
}
63+
if (! isset($token['access_token'])) {
64+
throw new Google_Auth_Exception("Invalid token format");
65+
}
66+
$token['created'] = time();
67+
$this->token = $token;
68+
}
69+
70+
public function getAccessToken()
71+
{
72+
return json_encode($this->token);
73+
}
74+
75+
/**
76+
* Acquires a new access token from the compute engine metadata server.
77+
* @throws Google_Auth_Exception
78+
*/
79+
public function acquireAccessToken(){
80+
$request = new Google_Http_Request(
81+
self::METADATA_AUTH_URL,
82+
'GET',
83+
array(
84+
'Metadata-Flavor' => 'Google'
85+
)
86+
);
87+
$request->disableGzip();
88+
$response = $this->client->getIo()->makeRequest($request);
89+
90+
if ($response->getResponseHttpCode() == 200) {
91+
$this->setAccessToken($response->getResponseBody());
92+
$this->token['created'] = time();
93+
return $this->getAccessToken();
94+
} else {
95+
throw new Google_Auth_Exception(
96+
sprintf(
97+
"Error fetching service account access token, message: '%s'",
98+
$response->getResponseBody()
99+
),
100+
$response->getResponseHttpCode()
101+
);
102+
}
103+
}
104+
105+
/**
106+
* Include an accessToken in a given apiHttpRequest.
107+
* @param Google_Http_Request $request
108+
* @return Google_Http_Request
109+
* @throws Google_Auth_Exception
110+
*/
111+
public function sign(Google_Http_Request $request)
112+
{
113+
if($this->isAccessTokenExpired()) {
114+
$this->acquireAccessToken();
115+
}
116+
117+
$this->client->getLogger()->debug('Compute engine service account authentication');
118+
119+
$request->setRequestHeaders(
120+
array('Authorization' => 'Bearer ' . $this->token['access_token'])
121+
);
122+
123+
return $request;
124+
}
125+
126+
/**
127+
* Returns if the access_token is expired.
128+
* @return bool Returns True if the access_token is expired.
129+
*/
130+
public function isAccessTokenExpired()
131+
{
132+
if (!$this->token || !isset($this->token['created'])) {
133+
return true;
134+
}
135+
136+
// If the token is set to expire in the next 30 seconds.
137+
$expired = ($this->token['created']
138+
+ ($this->token['expires_in'] - 30)) < time();
139+
140+
return $expired;
141+
}
142+
}

0 commit comments

Comments
 (0)