PluginProbe ʕ •ᴥ•ʔ
Transferito: WP Migration / trunk
Transferito: WP Migration vtrunk
trunk 11.4.0 12.0.0 13.1.0 14.0.0 14.0.11 14.0.7 14.1.0 14.1.1 14.1.2 14.1.3 14.1.4
transferito / vendor / aws / aws-sdk-php / src / Endpoint / Partition.php
transferito / vendor / aws / aws-sdk-php / src / Endpoint Last commit date
UseDualstackEndpoint 11 months ago UseFipsEndpoint 11 months ago EndpointProvider.php 11 months ago Partition.php 11 months ago PartitionEndpointProvider.php 11 months ago PartitionInterface.php 11 months ago PatternEndpointProvider.php 11 months ago
Partition.php
323 lines
1 <?php
2 namespace Aws\Endpoint;
3
4 use ArrayAccess;
5 use Aws\HasDataTrait;
6 use Aws\Sts\RegionalEndpoints\ConfigurationProvider;
7 use Aws\S3\RegionalEndpoint\ConfigurationProvider as S3ConfigurationProvider;
8 use InvalidArgumentException as Iae;
9
10 /**
11 * Default implementation of an AWS partition.
12 */
13 final class Partition implements ArrayAccess, PartitionInterface
14 {
15 use HasDataTrait;
16
17 private $stsLegacyGlobalRegions = [
18 'ap-northeast-1',
19 'ap-south-1',
20 'ap-southeast-1',
21 'ap-southeast-2',
22 'aws-global',
23 'ca-central-1',
24 'eu-central-1',
25 'eu-north-1',
26 'eu-west-1',
27 'eu-west-2',
28 'eu-west-3',
29 'sa-east-1',
30 'us-east-1',
31 'us-east-2',
32 'us-west-1',
33 'us-west-2',
34 ];
35
36 /**
37 * The partition constructor accepts the following options:
38 *
39 * - `partition`: (string, required) The partition name as specified in an
40 * ARN (e.g., `aws`)
41 * - `partitionName`: (string) The human readable name of the partition
42 * (e.g., "AWS Standard")
43 * - `dnsSuffix`: (string, required) The DNS suffix of the partition. This
44 * value is used to determine how endpoints in the partition are resolved.
45 * - `regionRegex`: (string) A PCRE regular expression that specifies the
46 * pattern that region names in the endpoint adhere to.
47 * - `regions`: (array, required) A map of the regions in the partition.
48 * Each key is the region as present in a hostname (e.g., `us-east-1`),
49 * and each value is a structure containing region information.
50 * - `defaults`: (array) A map of default key value pairs to apply to each
51 * endpoint of the partition. Any value in an `endpoint` definition will
52 * supersede any values specified in `defaults`.
53 * - `services`: (array, required) A map of service endpoint prefix name
54 * (the value found in a hostname) to information about the service.
55 *
56 * @param array $definition
57 *
58 * @throws Iae if any required options are missing
59 */
60 public function __construct(array $definition)
61 {
62 foreach (['partition', 'regions', 'services', 'dnsSuffix'] as $key) {
63 if (!isset($definition[$key])) {
64 throw new Iae("Partition missing required $key field");
65 }
66 }
67
68 $this->data = $definition;
69 }
70
71 public function getName()
72 {
73 return $this->data['partition'];
74 }
75
76 /**
77 * @internal
78 * @return mixed
79 */
80 public function getDnsSuffix()
81 {
82 return $this->data['dnsSuffix'];
83 }
84
85 public function isRegionMatch($region, $service)
86 {
87 if (isset($this->data['regions'][$region])
88 || isset($this->data['services'][$service]['endpoints'][$region])
89 ) {
90 return true;
91 }
92
93 if (isset($this->data['regionRegex'])) {
94 return (bool) preg_match(
95 "@{$this->data['regionRegex']}@",
96 $region
97 );
98 }
99
100 return false;
101 }
102
103 public function getAvailableEndpoints(
104 $service,
105 $allowNonRegionalEndpoints = false
106 ) {
107 if ($this->isServicePartitionGlobal($service)) {
108 return [$this->getPartitionEndpoint($service)];
109 }
110
111 if (isset($this->data['services'][$service]['endpoints'])) {
112 $serviceRegions = array_keys(
113 $this->data['services'][$service]['endpoints']
114 );
115
116 return $allowNonRegionalEndpoints
117 ? $serviceRegions
118 : array_intersect($serviceRegions, array_keys(
119 $this->data['regions']
120 ));
121 }
122
123 return [];
124 }
125
126 public function __invoke(array $args = [])
127 {
128 $service = isset($args['service']) ? $args['service'] : '';
129 $region = isset($args['region']) ? $args['region'] : '';
130 $scheme = isset($args['scheme']) ? $args['scheme'] : 'https';
131 $options = isset($args['options']) ? $args['options'] : [];
132 $data = $this->getEndpointData($service, $region, $options);
133 $variant = $this->getVariant($options, $data);
134 if (isset($variant['hostname'])) {
135 $template = $variant['hostname'];
136 } else {
137 $template = isset($data['hostname']) ? $data['hostname'] : '';
138 }
139 $dnsSuffix = isset($variant['dnsSuffix'])
140 ? $variant['dnsSuffix']
141 : $this->data['dnsSuffix'];
142 return [
143 'endpoint' => "{$scheme}://" . $this->formatEndpoint(
144 $template,
145 $service,
146 $region,
147 $dnsSuffix
148 ),
149 'signatureVersion' => $this->getSignatureVersion($data),
150 'signingRegion' => isset($data['credentialScope']['region'])
151 ? $data['credentialScope']['region']
152 : $region,
153 'signingName' => isset($data['credentialScope']['service'])
154 ? $data['credentialScope']['service']
155 : $service,
156 ];
157 }
158
159 private function getEndpointData($service, $region, $options)
160 {
161 $defaultRegion = $this->resolveRegion($service, $region, $options);
162 $data = isset($this->data['services'][$service]['endpoints'][$defaultRegion])
163 ? $this->data['services'][$service]['endpoints'][$defaultRegion]
164 : [];
165 $data += isset($this->data['services'][$service]['defaults'])
166 ? $this->data['services'][$service]['defaults']
167 : [];
168 $data += isset($this->data['defaults'])
169 ? $this->data['defaults']
170 : [];
171
172 return $data;
173 }
174
175 private function getSignatureVersion(array $data)
176 {
177 static $supportedBySdk = [
178 's3v4',
179 'v4',
180 'anonymous',
181 ];
182
183 $possibilities = array_intersect(
184 $supportedBySdk,
185 isset($data['signatureVersions'])
186 ? $data['signatureVersions']
187 : ['v4']
188 );
189
190 return array_shift($possibilities);
191 }
192
193 private function resolveRegion($service, $region, $options)
194 {
195 if (isset($this->data['services'][$service]['endpoints'][$region])
196 && $this->isFipsEndpointUsed($region)
197 ) {
198 return $region;
199 }
200
201 if ($this->isServicePartitionGlobal($service)
202 || $this->isStsLegacyEndpointUsed($service, $region, $options)
203 || $this->isS3LegacyEndpointUsed($service, $region, $options)
204 ) {
205 return $this->getPartitionEndpoint($service);
206 }
207
208 return $region;
209 }
210
211 private function isServicePartitionGlobal($service)
212 {
213 return isset($this->data['services'][$service]['isRegionalized'])
214 && false === $this->data['services'][$service]['isRegionalized']
215 && isset($this->data['services'][$service]['partitionEndpoint']);
216 }
217
218 /**
219 * STS legacy endpoints used for valid regions unless option is explicitly
220 * set to 'regional'
221 *
222 * @param string $service
223 * @param string $region
224 * @param array $options
225 * @return bool
226 */
227 private function isStsLegacyEndpointUsed($service, $region, $options)
228 {
229 return $service === 'sts'
230 && in_array($region, $this->stsLegacyGlobalRegions)
231 && (empty($options['sts_regional_endpoints'])
232 || ConfigurationProvider::unwrap(
233 $options['sts_regional_endpoints']
234 )->getEndpointsType() !== 'regional'
235 );
236 }
237
238 /**
239 * S3 legacy us-east-1 endpoint used for valid regions unless option is explicitly
240 * set to 'regional'
241 *
242 * @param string $service
243 * @param string $region
244 * @param array $options
245 * @return bool
246 */
247 private function isS3LegacyEndpointUsed($service, $region, $options)
248 {
249 return $service === 's3'
250 && $region === 'us-east-1'
251 && (empty($options['s3_us_east_1_regional_endpoint'])
252 || S3ConfigurationProvider::unwrap(
253 $options['s3_us_east_1_regional_endpoint']
254 )->getEndpointsType() !== 'regional'
255 );
256 }
257
258 private function getPartitionEndpoint($service)
259 {
260 return $this->data['services'][$service]['partitionEndpoint'];
261 }
262
263 private function formatEndpoint($template, $service, $region, $dnsSuffix)
264 {
265 return strtr($template, [
266 '{service}' => $service,
267 '{region}' => $region,
268 '{dnsSuffix}' => $dnsSuffix,
269 ]);
270 }
271
272 /**
273 * @param $region
274 * @return bool
275 */
276 private function isFipsEndpointUsed($region)
277 {
278 return strpos($region, "fips") !== false;
279 }
280
281 /**
282 * @param array $options
283 * @param array $data
284 * @return array
285 */
286 private function getVariant(array $options, array $data)
287 {
288 $variantTags = [];
289 if (isset($options['use_fips_endpoint'])) {
290 $useFips = $options['use_fips_endpoint'];
291 if (is_bool($useFips)) {
292 $useFips && $variantTags[] = 'fips';
293 } elseif ($useFips->isUseFipsEndpoint()) {
294 $variantTags[] = 'fips';
295 }
296 }
297 if (isset($options['use_dual_stack_endpoint'])) {
298 $useDualStack = $options['use_dual_stack_endpoint'];
299 if (is_bool($useDualStack)) {
300 $useDualStack && $variantTags[] = 'dualstack';
301 } elseif ($useDualStack->isUseDualStackEndpoint()) {
302 $variantTags[] = 'dualstack';
303 }
304 }
305 if (!empty($variantTags)) {
306 if (isset($data['variants'])) {
307 foreach ($data['variants'] as $variant) {
308 if (array_count_values($variant['tags']) == array_count_values($variantTags)) {
309 return $variant;
310 }
311 }
312 }
313 if (isset($this->data['defaults']['variants'])) {
314 foreach ($this->data['defaults']['variants'] as $variant) {
315 if (array_count_values($variant['tags']) == array_count_values($variantTags)) {
316 return $variant;
317 }
318 }
319 }
320 }
321 }
322 }
323