in src/Credentials/InstanceProfileProvider.php [104:241]
public function __invoke($previousCredentials = null)
{
$this->attempts = 0;
return Promise\Coroutine::of(function () use ($previousCredentials) {
// Retrieve token or switch out of secure mode
$token = null;
while ($this->secureMode && is_null($token)) {
try {
$token = (yield $this->request(
self::TOKEN_PATH,
'PUT',
[
'x-aws-ec2-metadata-token-ttl-seconds' => self::DEFAULT_TOKEN_TTL_SECONDS
]
));
} catch (TransferException $e) {
if ($this->getExceptionStatusCode($e) === 500
&& $previousCredentials instanceof Credentials
) {
goto generateCredentials;
} elseif ($this->shouldFallbackToIMDSv1()
&& (!method_exists($e, 'getResponse')
|| empty($e->getResponse())
|| !in_array(
$e->getResponse()->getStatusCode(),
[400, 500, 502, 503, 504]
))
) {
$this->secureMode = false;
} else {
$this->handleRetryableException(
$e,
[],
$this->createErrorMessage(
'Error retrieving metadata token'
)
);
}
}
$this->attempts++;
}
// Set token header only for secure mode
$headers = [];
if ($this->secureMode) {
$headers = [
'x-aws-ec2-metadata-token' => $token
];
}
// Retrieve profile
while (!$this->profile) {
try {
$this->profile = (yield $this->request(
self::CRED_PATH,
'GET',
$headers
));
} catch (TransferException $e) {
// 401 indicates insecure flow not supported, switch to
// attempting secure mode for subsequent calls
if (!empty($this->getExceptionStatusCode($e))
&& $this->getExceptionStatusCode($e) === 401
) {
$this->secureMode = true;
}
$this->handleRetryableException(
$e,
[ 'blacklist' => [401, 403] ],
$this->createErrorMessage($e->getMessage())
);
}
$this->attempts++;
}
// Retrieve credentials
$result = null;
while ($result == null) {
try {
$json = (yield $this->request(
self::CRED_PATH . $this->profile,
'GET',
$headers
));
$result = $this->decodeResult($json);
} catch (InvalidJsonException $e) {
$this->handleRetryableException(
$e,
[ 'blacklist' => [401, 403] ],
$this->createErrorMessage(
'Invalid JSON response, retries exhausted'
)
);
} catch (TransferException $e) {
// 401 indicates insecure flow not supported, switch to
// attempting secure mode for subsequent calls
if (($this->getExceptionStatusCode($e) === 500
|| strpos($e->getMessage(), "cURL error 28") !== false)
&& $previousCredentials instanceof Credentials
) {
goto generateCredentials;
} elseif (!empty($this->getExceptionStatusCode($e))
&& $this->getExceptionStatusCode($e) === 401
) {
$this->secureMode = true;
}
$this->handleRetryableException(
$e,
[ 'blacklist' => [401, 403] ],
$this->createErrorMessage($e->getMessage())
);
}
$this->attempts++;
}
generateCredentials:
if (!isset($result)) {
$credentials = $previousCredentials;
} else {
$credentials = new Credentials(
$result['AccessKeyId'],
$result['SecretAccessKey'],
$result['Token'],
strtotime($result['Expiration']),
$result['AccountId'] ?? null,
CredentialSources::IMDS
);
}
if ($credentials->isExpired()) {
$credentials->extendExpiration();
}
yield $credentials;
});
}