PluginProbe
Media Cloud Sync / 1.3.11
Media Cloud Sync v1.3.11
1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 All 34 releases
media-cloud-sync / includes / sdk / s3 / Aws / Auth / AuthSchemeResolver.php

AuthSchemeResolver.php in Media Cloud Sync 1.3.11, at includes/sdk/s3/Aws/Auth/AuthSchemeResolver.php

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