source: vendor/google/auth/src/CredentialsLoader.php@ f9c482b

Last change on this file since f9c482b was f9c482b, checked in by Vlado 222039 <vlado.popovski@…>, 7 days ago

Upload new project files

  • Property mode set to 100644
File size: 9.5 KB
RevLine 
[f9c482b]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;
19
20use Google\Auth\Credentials\ExternalAccountCredentials;
21use Google\Auth\Credentials\ImpersonatedServiceAccountCredentials;
22use Google\Auth\Credentials\InsecureCredentials;
23use Google\Auth\Credentials\ServiceAccountCredentials;
24use Google\Auth\Credentials\UserRefreshCredentials;
25use RuntimeException;
26use UnexpectedValueException;
27
28/**
29 * CredentialsLoader contains the behaviour used to locate and find default
30 * credentials files on the file system.
31 */
32abstract class CredentialsLoader implements
33 GetUniverseDomainInterface,
34 FetchAuthTokenInterface,
35 UpdateMetadataInterface
36{
37 use UpdateMetadataTrait;
38
39 const TOKEN_CREDENTIAL_URI = 'https://oauth2.googleapis.com/token';
40 const ENV_VAR = 'GOOGLE_APPLICATION_CREDENTIALS';
41 const QUOTA_PROJECT_ENV_VAR = 'GOOGLE_CLOUD_QUOTA_PROJECT';
42 const WELL_KNOWN_PATH = 'gcloud/application_default_credentials.json';
43 const NON_WINDOWS_WELL_KNOWN_PATH_BASE = '.config';
44 const MTLS_WELL_KNOWN_PATH = '.secureConnect/context_aware_metadata.json';
45 const MTLS_CERT_ENV_VAR = 'GOOGLE_API_USE_CLIENT_CERTIFICATE';
46
47 /**
48 * @param string $cause
49 * @return string
50 */
51 private static function unableToReadEnv($cause)
52 {
53 $msg = 'Unable to read the credential file specified by ';
54 $msg .= ' GOOGLE_APPLICATION_CREDENTIALS: ';
55 $msg .= $cause;
56
57 return $msg;
58 }
59
60 /**
61 * @return bool
62 */
63 private static function isOnWindows()
64 {
65 return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
66 }
67
68 /**
69 * Load a JSON key from the path specified in the environment.
70 *
71 * Load a JSON key from the path specified in the environment
72 * variable GOOGLE_APPLICATION_CREDENTIALS. Return null if
73 * GOOGLE_APPLICATION_CREDENTIALS is not specified.
74 *
75 * @return array<mixed>|null JSON key | null
76 */
77 public static function fromEnv()
78 {
79 $path = getenv(self::ENV_VAR);
80 if (empty($path)) {
81 return null;
82 }
83 if (!file_exists($path)) {
84 $cause = 'file ' . $path . ' does not exist';
85 throw new \DomainException(self::unableToReadEnv($cause));
86 }
87 $jsonKey = file_get_contents($path);
88 return json_decode((string) $jsonKey, true);
89 }
90
91 /**
92 * Load a JSON key from a well known path.
93 *
94 * The well known path is OS dependent:
95 *
96 * * windows: %APPDATA%/gcloud/application_default_credentials.json
97 * * others: $HOME/.config/gcloud/application_default_credentials.json
98 *
99 * If the file does not exist, this returns null.
100 *
101 * @return array<mixed>|null JSON key | null
102 */
103 public static function fromWellKnownFile()
104 {
105 $rootEnv = self::isOnWindows() ? 'APPDATA' : 'HOME';
106 $path = [getenv($rootEnv)];
107 if (!self::isOnWindows()) {
108 $path[] = self::NON_WINDOWS_WELL_KNOWN_PATH_BASE;
109 }
110 $path[] = self::WELL_KNOWN_PATH;
111 $path = implode(DIRECTORY_SEPARATOR, $path);
112 if (!file_exists($path)) {
113 return null;
114 }
115 $jsonKey = file_get_contents($path);
116 return json_decode((string) $jsonKey, true);
117 }
118
119 /**
120 * Create a new Credentials instance.
121 *
122 * @param string|string[] $scope the scope of the access request, expressed
123 * either as an Array or as a space-delimited String.
124 * @param array<mixed> $jsonKey the JSON credentials.
125 * @param string|string[] $defaultScope The default scope to use if no
126 * user-defined scopes exist, expressed either as an Array or as a
127 * space-delimited string.
128 *
129 * @return ServiceAccountCredentials|UserRefreshCredentials|ImpersonatedServiceAccountCredentials|ExternalAccountCredentials
130 */
131 public static function makeCredentials(
132 $scope,
133 array $jsonKey,
134 $defaultScope = null
135 ) {
136 if (!array_key_exists('type', $jsonKey)) {
137 throw new \InvalidArgumentException('json key is missing the type field');
138 }
139
140 if ($jsonKey['type'] == 'service_account') {
141 // Do not pass $defaultScope to ServiceAccountCredentials
142 return new ServiceAccountCredentials($scope, $jsonKey);
143 }
144
145 if ($jsonKey['type'] == 'authorized_user') {
146 $anyScope = $scope ?: $defaultScope;
147 return new UserRefreshCredentials($anyScope, $jsonKey);
148 }
149
150 if ($jsonKey['type'] == 'impersonated_service_account') {
151 $anyScope = $scope ?: $defaultScope;
152 return new ImpersonatedServiceAccountCredentials($anyScope, $jsonKey);
153 }
154
155 if ($jsonKey['type'] == 'external_account') {
156 $anyScope = $scope ?: $defaultScope;
157 return new ExternalAccountCredentials($anyScope, $jsonKey);
158 }
159
160 throw new \InvalidArgumentException('invalid value in the type field');
161 }
162
163 /**
164 * Create an authorized HTTP Client from an instance of FetchAuthTokenInterface.
165 *
166 * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
167 * @param array<mixed> $httpClientOptions (optional) Array of request options to apply.
168 * @param callable|null $httpHandler (optional) http client to fetch the token.
169 * @param callable|null $tokenCallback (optional) function to be called when a new token is fetched.
170 * @return \GuzzleHttp\Client
171 */
172 public static function makeHttpClient(
173 FetchAuthTokenInterface $fetcher,
174 array $httpClientOptions = [],
175 ?callable $httpHandler = null,
176 ?callable $tokenCallback = null
177 ) {
178 $middleware = new Middleware\AuthTokenMiddleware(
179 $fetcher,
180 $httpHandler,
181 $tokenCallback
182 );
183 $stack = \GuzzleHttp\HandlerStack::create();
184 $stack->push($middleware);
185
186 return new \GuzzleHttp\Client([
187 'handler' => $stack,
188 'auth' => 'google_auth',
189 ] + $httpClientOptions);
190 }
191
192 /**
193 * Create a new instance of InsecureCredentials.
194 *
195 * @return InsecureCredentials
196 */
197 public static function makeInsecureCredentials()
198 {
199 return new InsecureCredentials();
200 }
201
202 /**
203 * Fetch a quota project from the environment variable
204 * GOOGLE_CLOUD_QUOTA_PROJECT. Return null if
205 * GOOGLE_CLOUD_QUOTA_PROJECT is not specified.
206 *
207 * @return string|null
208 */
209 public static function quotaProjectFromEnv()
210 {
211 return getenv(self::QUOTA_PROJECT_ENV_VAR) ?: null;
212 }
213
214 /**
215 * Gets a callable which returns the default device certification.
216 *
217 * @throws UnexpectedValueException
218 * @return callable|null
219 */
220 public static function getDefaultClientCertSource()
221 {
222 if (!$clientCertSourceJson = self::loadDefaultClientCertSourceFile()) {
223 return null;
224 }
225 $clientCertSourceCmd = $clientCertSourceJson['cert_provider_command'];
226
227 return function () use ($clientCertSourceCmd) {
228 $cmd = array_map('escapeshellarg', $clientCertSourceCmd);
229 exec(implode(' ', $cmd), $output, $returnVar);
230
231 if (0 === $returnVar) {
232 return implode(PHP_EOL, $output);
233 }
234 throw new RuntimeException(
235 '"cert_provider_command" failed with a nonzero exit code'
236 );
237 };
238 }
239
240 /**
241 * Determines whether or not the default device certificate should be loaded.
242 *
243 * @return bool
244 */
245 public static function shouldLoadClientCertSource()
246 {
247 return filter_var(getenv(self::MTLS_CERT_ENV_VAR), FILTER_VALIDATE_BOOLEAN);
248 }
249
250 /**
251 * @return array{cert_provider_command:string[]}|null
252 */
253 private static function loadDefaultClientCertSourceFile()
254 {
255 $rootEnv = self::isOnWindows() ? 'APPDATA' : 'HOME';
256 $path = sprintf('%s/%s', getenv($rootEnv), self::MTLS_WELL_KNOWN_PATH);
257 if (!file_exists($path)) {
258 return null;
259 }
260 $jsonKey = file_get_contents($path);
261 $clientCertSourceJson = json_decode((string) $jsonKey, true);
262 if (!$clientCertSourceJson) {
263 throw new UnexpectedValueException('Invalid client cert source JSON');
264 }
265 if (!isset($clientCertSourceJson['cert_provider_command'])) {
266 throw new UnexpectedValueException(
267 'cert source requires "cert_provider_command"'
268 );
269 }
270 if (!is_array($clientCertSourceJson['cert_provider_command'])) {
271 throw new UnexpectedValueException(
272 'cert source expects "cert_provider_command" to be an array'
273 );
274 }
275 return $clientCertSourceJson;
276 }
277
278 /**
279 * Get the universe domain from the credential. Defaults to "googleapis.com"
280 * for all credential types which do not support universe domain.
281 *
282 * @return string
283 */
284 public function getUniverseDomain(): string
285 {
286 return self::DEFAULT_UNIVERSE_DOMAIN;
287 }
288}
Note: See TracBrowser for help on using the repository browser.