Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
namespace Aws\Credentials;
3
 
4
use Aws\Exception\AwsException;
5
use Aws\Exception\CredentialsException;
6
use Aws\Result;
7
use Aws\Sts\StsClient;
8
use GuzzleHttp\Promise;
9
 
10
/**
11
 * Credential provider that provides credentials via assuming a role with a web identity
12
 * More Information, see: https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-sts-2011-06-15.html#assumerolewithwebidentity
13
 */
14
class AssumeRoleWithWebIdentityCredentialProvider
15
{
16
    const ERROR_MSG = "Missing required 'AssumeRoleWithWebIdentityCredentialProvider' configuration option: ";
17
    const ENV_RETRIES = 'AWS_METADATA_SERVICE_NUM_ATTEMPTS';
18
 
19
    /** @var string */
20
    private $tokenFile;
21
 
22
    /** @var string */
23
    private $arn;
24
 
25
    /** @var string */
26
    private $session;
27
 
28
    /** @var StsClient */
29
    private $client;
30
 
31
    /** @var integer */
32
    private $retries;
33
 
34
    /** @var integer */
35
    private $authenticationAttempts;
36
 
37
    /** @var integer */
38
    private $tokenFileReadAttempts;
39
 
40
    /**
41
     * The constructor attempts to load config from environment variables.
42
     * If not set, the following config options are used:
43
     *  - WebIdentityTokenFile: full path of token filename
44
     *  - RoleArn: arn of role to be assumed
45
     *  - SessionName: (optional) set by SDK if not provided
46
     *
47
     * @param array $config Configuration options
48
     * @throws \InvalidArgumentException
49
     */
50
    public function __construct(array $config = [])
51
    {
52
        if (!isset($config['RoleArn'])) {
53
            throw new \InvalidArgumentException(self::ERROR_MSG . "'RoleArn'.");
54
        }
55
        $this->arn = $config['RoleArn'];
56
 
57
        if (!isset($config['WebIdentityTokenFile'])) {
58
            throw new \InvalidArgumentException(self::ERROR_MSG . "'WebIdentityTokenFile'.");
59
        }
60
        $this->tokenFile = $config['WebIdentityTokenFile'];
61
 
62
        if (!preg_match("/^\w\:|^\/|^\\\/", $this->tokenFile)) {
63
            throw new \InvalidArgumentException("'WebIdentityTokenFile' must be an absolute path.");
64
        }
65
 
66
        $this->retries = (int) getenv(self::ENV_RETRIES) ?: (isset($config['retries']) ? $config['retries'] : 3);
67
        $this->authenticationAttempts = 0;
68
        $this->tokenFileReadAttempts = 0;
69
 
70
        $this->session = isset($config['SessionName'])
71
            ? $config['SessionName']
72
            : 'aws-sdk-php-' . round(microtime(true) * 1000);
73
 
74
        $region = isset($config['region'])
75
            ? $config['region']
76
            : 'us-east-1';
77
 
78
        if (isset($config['client'])) {
79
            $this->client = $config['client'];
80
        } else {
81
            $this->client = new StsClient([
82
                'credentials' => false,
83
                'region' => $region,
84
                'version' => 'latest'
85
            ]);
86
        }
87
    }
88
 
89
    /**
90
     * Loads assume role with web identity credentials.
91
     *
92
     * @return Promise\PromiseInterface
93
     */
94
    public function __invoke()
95
    {
96
        return Promise\Coroutine::of(function () {
97
            $client = $this->client;
98
            $result = null;
99
            while ($result == null) {
100
                try {
101
                    $token = @file_get_contents($this->tokenFile);
102
                    if (false === $token) {
103
                        clearstatcache(true, dirname($this->tokenFile) . "/" . readlink($this->tokenFile));
104
                        clearstatcache(true, dirname($this->tokenFile) . "/" . dirname(readlink($this->tokenFile)));
105
                        clearstatcache(true, $this->tokenFile);
106
                        if (!@is_readable($this->tokenFile)) {
107
                            throw new CredentialsException(
108
                                "Unreadable tokenfile at location {$this->tokenFile}"
109
                            );
110
                        }
111
 
112
                        $token = @file_get_contents($this->tokenFile);
113
                    }
114
                    if (empty($token)) {
115
                        if ($this->tokenFileReadAttempts < $this->retries) {
116
                            sleep((int) pow(1.2, $this->tokenFileReadAttempts));
117
                            $this->tokenFileReadAttempts++;
118
                            continue;
119
                        }
120
                        throw new CredentialsException("InvalidIdentityToken from file: {$this->tokenFile}");
121
                    }
122
                } catch (\Exception $exception) {
123
                    throw new CredentialsException(
124
                        "Error reading WebIdentityTokenFile from " . $this->tokenFile,
125
                        0,
126
                        $exception
127
                    );
128
                }
129
 
130
                $assumeParams = [
131
                    'RoleArn' => $this->arn,
132
                    'RoleSessionName' => $this->session,
133
                    'WebIdentityToken' => $token
134
                ];
135
 
136
                try {
137
                    $result = $client->assumeRoleWithWebIdentity($assumeParams);
138
                } catch (AwsException $e) {
139
                    if ($e->getAwsErrorCode() == 'InvalidIdentityToken') {
140
                        if ($this->authenticationAttempts < $this->retries) {
141
                            sleep((int) pow(1.2, $this->authenticationAttempts));
142
                        } else {
143
                            throw new CredentialsException(
144
                                "InvalidIdentityToken, retries exhausted"
145
                            );
146
                        }
147
                    } else {
148
                        throw new CredentialsException(
149
                            "Error assuming role from web identity credentials",
150
                            0,
151
                            $e
152
                        );
153
                    }
154
                } catch (\Exception $e) {
155
                    throw new CredentialsException(
156
                        "Error retrieving web identity credentials: " . $e->getMessage()
157
                        . " (" . $e->getCode() . ")"
158
                    );
159
                }
160
                $this->authenticationAttempts++;
161
            }
162
 
163
            yield $this->client->createCredentials($result);
164
        });
165
    }
166
}