Skip to content

Commit

Permalink
fresh credentials
Browse files Browse the repository at this point in the history
  • Loading branch information
TsinghuaDream authored and yndu13 committed Jan 8, 2025
1 parent 462c949 commit 6054424
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 29 deletions.
93 changes: 93 additions & 0 deletions src/Credential/RefreshResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace AlibabaCloud\Credentials\Credential;

use AlibabaCloud\Credentials\Providers\Credentials;

class RefreshResult
{
public function __construct($credentials = [], $staleTime = null, $prefetchTime = null)
{
$this->credentials = $credentials;
$this->staleTime = $staleTime ? $staleTime : PHP_INT_MAX;
$this->prefetchTime = $prefetchTime ? $prefetchTime : PHP_INT_MAX;
}
public function validate()
{
}
public function toMap()
{
$res = [];
if (null !== $this->staleTime) {
$res['staleTime'] = $this->staleTime;
}
if (null !== $this->prefetchTime) {
$res['prefetchTime'] = $this->prefetchTime;
}
if (null !== $this->credentials) {
$res['credentials'] = $this->credentials;
}
return $res;
}
/**
* @param array $map
* @return RefreshResult
*/
public static function fromMap($map = [])
{
$model = new self();
if (isset($map['staleTime'])) {
$model->staleTime = $map['staleTime'];
}
if (isset($map['prefetchTime'])) {
$model->staleTime = $map['prefetchTime'];
}
if (isset($map['credentials'])) {
$model->staleTime = $map['credentials'];
}
return $model;
}
/**
* @description staleTime
* @var int
*/
public $staleTime;

/**
* @description prefetchTime
* @var int
*/
public $prefetchTime;

/**
* @description credentials
* @var Credentials
*/
public $credentials;


/**
* @return Credentials
*/
public function credentials()
{
return $this->credentials;
}

/**
* @var int
*/
public function staleTime()
{
return $this->staleTime;
}

/**
* @var int
*/
public function prefetchTime()
{
return $this->prefetchTime;
}

}
19 changes: 17 additions & 2 deletions src/Providers/EcsRamRoleCredentialsProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use GuzzleHttp\Exception\GuzzleException;
use InvalidArgumentException;
use RuntimeException;
use AlibabaCloud\Credentials\Credential\RefreshResult;

/**
* @internal This class is intended for internal use within the package.
Expand Down Expand Up @@ -116,7 +117,7 @@ private function filterDisableECSIMDSv1($params)
/**
* Get credentials by request.
*
* @return array
* @return RefreshResult
* @throws InvalidArgumentException
* @throws RuntimeException
* @throws GuzzleException
Expand Down Expand Up @@ -153,7 +154,13 @@ public function refreshCredentials()
throw new RuntimeException('Error retrieving credentials from IMDS result, Code is not Success:' . $result->toJson());
}

return $credentials;
return new RefreshResult(new Credentials([
'accessKeyId' => $credentials['AccessKeyId'],
'accessKeySecret' => $credentials['AccessKeySecret'],
'securityToken' => $credentials['SecurityToken'],
'expiration' => \strtotime($credentials['Expiration']),
'providerName' => $this->getProviderName(),
]), $this->getStaleTime(strtotime($credentials["Expiration"])), $this->getPrefetchTime(strtotime($credentials["Expiration"])));
}

/**
Expand Down Expand Up @@ -221,6 +228,14 @@ private function getMetadataToken()
return (string) $result;
}

/**
* @var int
*/
public function getPrefetchTime($expiration) {
return $expiration <= 0 ?
time() + (5 * 60) :
time() + (60 * 60);
}

/**
* @return string
Expand Down
11 changes: 9 additions & 2 deletions src/Providers/OIDCRoleArnCredentialsProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use InvalidArgumentException;
use RuntimeException;
use Exception;
use AlibabaCloud\Credentials\Credential\RefreshResult;

/**
* @internal This class is intended for internal use within the package.
Expand Down Expand Up @@ -199,7 +200,7 @@ private function filterOptions(array $options)
/**
* Get credentials by request.
*
* @return array
* @return RefreshResult
* @throws RuntimeException
* @throws GuzzleException
*/
Expand Down Expand Up @@ -242,7 +243,13 @@ public function refreshCredentials()
throw new RuntimeException('Error retrieving credentials from OIDC result:' . $result->toJson());
}

return $credentials;
return new RefreshResult(new Credentials([
'accessKeyId' => $credentials['AccessKeyId'],
'accessKeySecret' => $credentials['AccessKeySecret'],
'securityToken' => $credentials['SecurityToken'],
'expiration' => \strtotime($credentials['Expiration']),
'providerName' => $this->getProviderName(),
]), $this->getStaleTime(strtotime($credentials['Expiration'])) );
}

public function key()
Expand Down
11 changes: 9 additions & 2 deletions src/Providers/RamRoleArnCredentialsProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use GuzzleHttp\Exception\GuzzleException;
use InvalidArgumentException;
use RuntimeException;
use AlibabaCloud\Credentials\Credential\RefreshResult;

/**
* @internal This class is intended for internal use within the package.
Expand Down Expand Up @@ -200,7 +201,7 @@ private function filterOptions(array $options)
/**
* Get credentials by request.
*
* @return array
* @return RefreshResult
* @throws RuntimeException
* @throws GuzzleException
*/
Expand Down Expand Up @@ -252,7 +253,13 @@ public function refreshCredentials()
throw new RuntimeException('Error retrieving credentials from RamRoleArn result:' . $result->toJson());
}

return $credentials;
return new RefreshResult(new Credentials([
'accessKeyId' => $credentials['AccessKeyId'],
'accessKeySecret' => $credentials['AccessKeySecret'],
'securityToken' => $credentials['SecurityToken'],
'expiration' => \strtotime($credentials['Expiration']),
'providerName' => $this->getProviderName(),
]), $this->getStaleTime(strtotime($credentials['Expiration'])));
}

public function key()
Expand Down
11 changes: 9 additions & 2 deletions src/Providers/RsaKeyPairCredentialsProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use AlibabaCloud\Credentials\Request\Request;
use GuzzleHttp\Psr7\Uri;
use GuzzleHttp\Exception\GuzzleException;
use AlibabaCloud\Credentials\Credential\RefreshResult;

use InvalidArgumentException;
use RuntimeException;
Expand Down Expand Up @@ -116,7 +117,7 @@ private function filterSTSEndpoint(array $params)
/**
* Get credentials by request.
*
* @return array
* @return RefreshResult
* @throws RuntimeException
* @throws GuzzleException
*/
Expand Down Expand Up @@ -162,7 +163,13 @@ public function refreshCredentials()
$credentials['SecurityToken'] = null;


return $credentials;
return new RefreshResult(new Credentials([
'accessKeyId' => $credentials['AccessKeyId'],
'accessKeySecret' => $credentials['AccessKeySecret'],
'securityToken' => $credentials['SecurityToken'],
'expiration' => \strtotime($credentials['Expiration']),
'providerName' => $this->getProviderName(),
]), $this->getStaleTime(strtotime($credentials['Expiration'])));
}

public function key()
Expand Down
110 changes: 91 additions & 19 deletions src/Providers/SessionCredentialsProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace AlibabaCloud\Credentials\Providers;

use AlibabaCloud\Credentials\Credential\RefreshResult;

abstract class SessionCredentialsProvider implements CredentialsProvider
{
/**
Expand All @@ -24,26 +26,23 @@ abstract class SessionCredentialsProvider implements CredentialsProvider
/**
* Get the credentials from the cache in the validity period.
*
* @return array|null
* @return RefreshResult|null
*/
protected function getCredentialsInCache()
{
if (isset(self::$credentialsCache[$this->key()])) {
$result = self::$credentialsCache[$this->key()];
if (\strtotime($result['Expiration']) - \time() >= $this->expirationSlot) {
return $result;
}
return $result;
}

return null;
}

/**
* Cache credentials.
*
* @param array $credential
* @param RefreshResult $credential
*/
protected function cache(array $credential)
protected function cache(RefreshResult $credential)
{
self::$credentialsCache[$this->key()] = $credential;
}
Expand All @@ -55,25 +54,98 @@ protected function cache(array $credential)
*/
public function getCredentials()
{
$credentials = $this->getCredentialsInCache();
if ($this->cacheIsStale()) {
$result = $this->refreshCredentials();
$this->cache($result);
}else if ($this->shouldInitiateCachePrefetch()) {
$result = $this->refreshCache();
$this->cache($result);
}

if ($credentials === null) {
$credentials = $this->refreshCredentials();
$this->cache($credentials);
$result = $this->getCredentialsInCache();

return $result->credentials();
}

/**
* @var RefreshResult
*/
public function refreshCache()
{
try{
return($this->handleFetchedSuccess($this->refreshCredentials()));
}catch (\Exception $e){
$this->handleFetchedFailure($e);
}
}

protected function handleFetchedFailure(\Exception $e)
{
$currentCachedValue = $this->getCredentialsInCache();
if(is_null($currentCachedValue)){
throw $e;
}

if(time() < $currentCachedValue->staleTime()){
return $currentCachedValue;
}

return new Credentials([
'accessKeyId' => $credentials['AccessKeyId'],
'accessKeySecret' => $credentials['AccessKeySecret'],
'securityToken' => $credentials['SecurityToken'],
'expiration' => \strtotime($credentials['Expiration']),
'providerName' => $this->getProviderName(),
]);
throw $e;
}
/**
* @var RefreshResult
*/
protected function handleFetchedSuccess(RefreshResult $value)
{
$now = time();
// 过期时间大于15分钟,不用管
if($now < $value->staleTime()){
return $value;
}
// 不足或等于15分钟,但未过期,下次会再次刷新
if ($now < $value->staleTime() + 15 * 60) {
$value->staleTime = $now;
return $value;
}
// 已过期,看缓存,缓存若大于15分钟,返回缓存,若小于15分钟,则稍后重试
if (is_null( $this->getCredentialsInCache())){
throw new \Exception("No cached value was found.");
} else if ($now < $this->getCredentialsInCache()->staleTime()) {
return $this->getCredentialsInCache();
} else {
// 返回成功,延长有效期 1 分钟
$expectation = mt_rand(50, 70);
$value->staleTime = time() + $expectation;
return $value;
}
}

/**
* @var bool
*/
public function cacheIsStale()
{
return $this->getCredentialsInCache() === null || time() >= $this->getCredentialsInCache()->staleTime();
}

/**
* @var bool
*/
private function shouldInitiateCachePrefetch() {
return $this->getCredentialsInCache() === null || time() >= $this->getCredentialsInCache()->prefetchTime();
}

/**
* @return array
* @var int
*/
public function getStaleTime($expiration) {
return $expiration <= 0 ?
time() + (60 * 60) :
$expiration - (15 * 60);
}

/**
* @return RefreshResult
*/
abstract function refreshCredentials();

Expand Down
Loading

0 comments on commit 6054424

Please sign in to comment.