Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
 
3
namespace Aws\Auth;
4
 
5
use Aws\Auth\Exception\UnresolvedAuthSchemeException;
6
use Aws\Exception\CredentialsException;
7
use Aws\Exception\TokenException;
8
use Aws\Identity\AwsCredentialIdentity;
9
use Aws\Identity\BearerTokenIdentity;
10
use GuzzleHttp\Promise\PromiseInterface;
11
 
12
/**
13
 * Houses logic for selecting an auth scheme modeled in a service's `auth` trait.
14
 * The `auth` trait can be modeled either in a service's metadata, or at the operation level.
15
 */
16
class AuthSchemeResolver implements AuthSchemeResolverInterface
17
{
18
    const UNSIGNED_BODY = '-unsigned-body';
19
 
20
    /**
21
     * @var string[] Default mapping of modeled auth trait auth schemes
22
     *               to the SDK's supported signature versions.
23
     */
24
    private static $defaultAuthSchemeMap = [
25
        'aws.auth#sigv4' => 'v4',
26
        'aws.auth#sigv4a' => 'v4a',
27
        'smithy.api#httpBearerAuth' => 'bearer',
28
        'smithy.api#noAuth' => 'anonymous'
29
    ];
30
 
31
    /**
32
     * @var array Mapping of auth schemes to signature versions used in
33
     *            resolving a signature version.
34
     */
35
    private $authSchemeMap;
36
    private $tokenProvider;
37
    private $credentialProvider;
38
 
39
 
40
    public function __construct(
41
        callable $credentialProvider,
42
        ?callable $tokenProvider = null,
43
        array $authSchemeMap = []
44
    ){
45
        $this->credentialProvider = $credentialProvider;
46
        $this->tokenProvider = $tokenProvider;
47
        $this->authSchemeMap = empty($authSchemeMap)
48
            ? self::$defaultAuthSchemeMap
49
            : $authSchemeMap;
50
    }
51
 
52
    /**
53
     * Accepts a priority-ordered list of auth schemes and an Identity
54
     * and selects the first compatible auth schemes, returning a normalized
55
     * signature version.  For example, based on the default auth scheme mapping,
56
     * if `aws.auth#sigv4` is selected, `v4` will be returned.
57
     *
58
     * @param array $authSchemes
59
     * @param $identity
60
     *
61
     * @return string
62
     * @throws UnresolvedAuthSchemeException
63
     */
64
    public function selectAuthScheme(
65
        array $authSchemes,
66
        array $args = []
67
    ): string
68
    {
69
        $failureReasons = [];
70
 
71
        foreach($authSchemes as $authScheme) {
72
            $normalizedAuthScheme = $this->authSchemeMap[$authScheme] ?? $authScheme;
73
 
74
            if ($this->isCompatibleAuthScheme($normalizedAuthScheme)) {
75
                if ($normalizedAuthScheme === 'v4' && !empty($args['unsigned_payload'])) {
76
                    return $normalizedAuthScheme . self::UNSIGNED_BODY;
77
                }
78
 
79
                return $normalizedAuthScheme;
80
            } else {
81
                $failureReasons[] = $this->getIncompatibilityMessage($normalizedAuthScheme);
82
            }
83
        }
84
 
85
        throw new UnresolvedAuthSchemeException(
86
            'Could not resolve an authentication scheme: '
87
            . implode('; ', $failureReasons)
88
        );
89
    }
90
 
91
    /**
92
     * Determines compatibility based on either Identity or the availability
93
     * of the CRT extension.
94
     *
95
     * @param $authScheme
96
     *
97
     * @return bool
98
     */
99
    private function isCompatibleAuthScheme($authScheme): bool
100
    {
101
        switch ($authScheme) {
102
            case 'v4':
103
            case 'anonymous':
104
                return $this->hasAwsCredentialIdentity();
105
            case 'v4a':
106
                return extension_loaded('awscrt') && $this->hasAwsCredentialIdentity();
107
            case 'bearer':
108
                return $this->hasBearerTokenIdentity();
109
            default:
110
                return false;
111
        }
112
    }
113
 
114
    /**
115
     * Provides incompatibility messages in the event an incompatible auth scheme
116
     * is encountered.
117
     *
118
     * @param $authScheme
119
     *
120
     * @return string
121
     */
122
    private function getIncompatibilityMessage($authScheme): string
123
    {
124
        switch ($authScheme) {
125
            case 'v4':
126
                return 'Signature V4 requires AWS credentials for request signing';
127
            case 'anonymous':
128
                return 'Anonymous signatures require AWS credentials for request signing';
129
            case 'v4a':
130
                return 'The aws-crt-php extension and AWS credentials are required to use Signature V4A';
131
            case 'bearer':
132
                return 'Bearer token credentials must be provided to use Bearer authentication';
133
            default:
134
                return "The service does not support `{$authScheme}` authentication.";
135
        }
136
    }
137
 
138
    /**
139
     * @return bool
140
     */
141
    private function hasAwsCredentialIdentity(): bool
142
    {
143
        $fn = $this->credentialProvider;
144
        $result = $fn();
145
 
146
        if ($result instanceof PromiseInterface) {
147
            try {
148
                $resolved = $result->wait();
149
                return $resolved instanceof AwsCredentialIdentity;
150
            } catch (CredentialsException $e) {
151
                return false;
152
            }
153
        }
154
 
155
        return $result instanceof AwsCredentialIdentity;
156
    }
157
 
158
    /**
159
     * @return bool
160
     */
161
    private function hasBearerTokenIdentity(): bool
162
    {
163
        if ($this->tokenProvider) {
164
            $fn = $this->tokenProvider;
165
            $result = $fn();
166
 
167
            if ($result instanceof PromiseInterface) {
168
                try {
169
                    $resolved = $result->wait();
170
                    return $resolved instanceof BearerTokenIdentity;
171
                } catch (TokenException $e) {
172
                    return false;
173
                }
174
            }
175
 
176
            return $result instanceof BearerTokenIdentity;
177
        }
178
 
179
        return false;
180
    }
181
}