PluginProbe
Media Cloud Sync / 1.4.1
Media Cloud Sync v1.4.1
1.4.1 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 All 35 releases
media-cloud-sync / includes / sdk / s3 / Aws / Endpoint / Partition.php

Partition.php in Media Cloud Sync 1.4.1, at includes/sdk/s3/Aws/Endpoint/Partition.php

211 lines 9.2 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\Endpoint;
4
5 use ArrayAccess;
6 use Dudlewebs\WPMCS\s3\Aws\HasDataTrait;
7 use Dudlewebs\WPMCS\s3\Aws\Sts\RegionalEndpoints\ConfigurationProvider;
8 use Dudlewebs\WPMCS\s3\Aws\S3\RegionalEndpoint\ConfigurationProvider as S3ConfigurationProvider;
9 use InvalidArgumentException as Iae;
10 /**
11 * Default implementation of an AWS partition.
12 */
13 final class Partition implements ArrayAccess, PartitionInterface
14 {
15 use HasDataTrait;
16 private $stsLegacyGlobalRegions = ['ap-northeast-1', 'ap-south-1', 'ap-southeast-1', 'ap-southeast-2', 'aws-global', 'ca-central-1', 'eu-central-1', 'eu-north-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'sa-east-1', 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2'];
17 /**
18 * The partition constructor accepts the following options:
19 *
20 * - `partition`: (string, required) The partition name as specified in an
21 * ARN (e.g., `aws`)
22 * - `partitionName`: (string) The human readable name of the partition
23 * (e.g., "AWS Standard")
24 * - `dnsSuffix`: (string, required) The DNS suffix of the partition. This
25 * value is used to determine how endpoints in the partition are resolved.
26 * - `regionRegex`: (string) A PCRE regular expression that specifies the
27 * pattern that region names in the endpoint adhere to.
28 * - `regions`: (array, required) A map of the regions in the partition.
29 * Each key is the region as present in a hostname (e.g., `us-east-1`),
30 * and each value is a structure containing region information.
31 * - `defaults`: (array) A map of default key value pairs to apply to each
32 * endpoint of the partition. Any value in an `endpoint` definition will
33 * supersede any values specified in `defaults`.
34 * - `services`: (array, required) A map of service endpoint prefix name
35 * (the value found in a hostname) to information about the service.
36 *
37 * @param array $definition
38 *
39 * @throws Iae if any required options are missing
40 */
41 public function __construct(array $definition)
42 {
43 foreach (['partition', 'regions', 'services', 'dnsSuffix'] as $key) {
44 if (!isset($definition[$key])) {
45 throw new Iae("Partition missing required {$key} field");
46 }
47 }
48 $this->data = $definition;
49 }
50 public function getName()
51 {
52 return $this->data['partition'];
53 }
54 /**
55 * @internal
56 * @return mixed
57 */
58 public function getDnsSuffix()
59 {
60 return $this->data['dnsSuffix'];
61 }
62 public function isRegionMatch($region, $service)
63 {
64 if (isset($this->data['regions'][$region]) || isset($this->data['services'][$service]['endpoints'][$region])) {
65 return \true;
66 }
67 if (isset($this->data['regionRegex'])) {
68 return (bool) \preg_match("@{$this->data['regionRegex']}@", $region);
69 }
70 return \false;
71 }
72 public function getAvailableEndpoints($service, $allowNonRegionalEndpoints = \false)
73 {
74 if ($this->isServicePartitionGlobal($service)) {
75 return [$this->getPartitionEndpoint($service)];
76 }
77 if (isset($this->data['services'][$service]['endpoints'])) {
78 $serviceRegions = \array_keys($this->data['services'][$service]['endpoints']);
79 return $allowNonRegionalEndpoints ? $serviceRegions : \array_intersect($serviceRegions, \array_keys($this->data['regions']));
80 }
81 return [];
82 }
83 public function __invoke(array $args = [])
84 {
85 $service = isset($args['service']) ? $args['service'] : '';
86 $region = isset($args['region']) ? $args['region'] : '';
87 $scheme = isset($args['scheme']) ? $args['scheme'] : 'https';
88 $options = isset($args['options']) ? $args['options'] : [];
89 $data = $this->getEndpointData($service, $region, $options);
90 $variant = $this->getVariant($options, $data);
91 if (isset($variant['hostname'])) {
92 $template = $variant['hostname'];
93 } else {
94 $template = isset($data['hostname']) ? $data['hostname'] : '';
95 }
96 $dnsSuffix = isset($variant['dnsSuffix']) ? $variant['dnsSuffix'] : $this->data['dnsSuffix'];
97 return ['endpoint' => "{$scheme}://" . $this->formatEndpoint($template, $service, $region, $dnsSuffix), 'signatureVersion' => $this->getSignatureVersion($data), 'signingRegion' => isset($data['credentialScope']['region']) ? $data['credentialScope']['region'] : $region, 'signingName' => isset($data['credentialScope']['service']) ? $data['credentialScope']['service'] : $service];
98 }
99 private function getEndpointData($service, $region, $options)
100 {
101 $defaultRegion = $this->resolveRegion($service, $region, $options);
102 $data = isset($this->data['services'][$service]['endpoints'][$defaultRegion]) ? $this->data['services'][$service]['endpoints'][$defaultRegion] : [];
103 $data += isset($this->data['services'][$service]['defaults']) ? $this->data['services'][$service]['defaults'] : [];
104 $data += isset($this->data['defaults']) ? $this->data['defaults'] : [];
105 return $data;
106 }
107 private function getSignatureVersion(array $data)
108 {
109 static $supportedBySdk = ['s3v4', 'v4', 'anonymous'];
110 $possibilities = \array_intersect($supportedBySdk, isset($data['signatureVersions']) ? $data['signatureVersions'] : ['v4']);
111 return \array_shift($possibilities);
112 }
113 private function resolveRegion($service, $region, $options)
114 {
115 if (isset($this->data['services'][$service]['endpoints'][$region]) && $this->isFipsEndpointUsed($region)) {
116 return $region;
117 }
118 if ($this->isServicePartitionGlobal($service) || $this->isStsLegacyEndpointUsed($service, $region, $options) || $this->isS3LegacyEndpointUsed($service, $region, $options)) {
119 return $this->getPartitionEndpoint($service);
120 }
121 return $region;
122 }
123 private function isServicePartitionGlobal($service)
124 {
125 return isset($this->data['services'][$service]['isRegionalized']) && \false === $this->data['services'][$service]['isRegionalized'] && isset($this->data['services'][$service]['partitionEndpoint']);
126 }
127 /**
128 * STS legacy endpoints used for valid regions unless option is explicitly
129 * set to 'regional'
130 *
131 * @param string $service
132 * @param string $region
133 * @param array $options
134 * @return bool
135 */
136 private function isStsLegacyEndpointUsed($service, $region, $options)
137 {
138 return $service === 'sts' && \in_array($region, $this->stsLegacyGlobalRegions) && (empty($options['sts_regional_endpoints']) || ConfigurationProvider::unwrap($options['sts_regional_endpoints'])->getEndpointsType() !== 'regional');
139 }
140 /**
141 * S3 legacy us-east-1 endpoint used for valid regions unless option is explicitly
142 * set to 'regional'
143 *
144 * @param string $service
145 * @param string $region
146 * @param array $options
147 * @return bool
148 */
149 private function isS3LegacyEndpointUsed($service, $region, $options)
150 {
151 return $service === 's3' && $region === 'us-east-1' && (empty($options['s3_us_east_1_regional_endpoint']) || S3ConfigurationProvider::unwrap($options['s3_us_east_1_regional_endpoint'])->getEndpointsType() !== 'regional');
152 }
153 private function getPartitionEndpoint($service)
154 {
155 return $this->data['services'][$service]['partitionEndpoint'];
156 }
157 private function formatEndpoint($template, $service, $region, $dnsSuffix)
158 {
159 return \strtr($template, ['{service}' => $service, '{region}' => $region, '{dnsSuffix}' => $dnsSuffix]);
160 }
161 /**
162 * @param $region
163 * @return bool
164 */
165 private function isFipsEndpointUsed($region)
166 {
167 return \strpos($region, "fips") !== \false;
168 }
169 /**
170 * @param array $options
171 * @param array $data
172 * @return array
173 */
174 private function getVariant(array $options, array $data)
175 {
176 $variantTags = [];
177 if (isset($options['use_fips_endpoint'])) {
178 $useFips = $options['use_fips_endpoint'];
179 if (\is_bool($useFips)) {
180 $useFips && ($variantTags[] = 'fips');
181 } elseif ($useFips->isUseFipsEndpoint()) {
182 $variantTags[] = 'fips';
183 }
184 }
185 if (isset($options['use_dual_stack_endpoint'])) {
186 $useDualStack = $options['use_dual_stack_endpoint'];
187 if (\is_bool($useDualStack)) {
188 $useDualStack && ($variantTags[] = 'dualstack');
189 } elseif ($useDualStack->isUseDualStackEndpoint()) {
190 $variantTags[] = 'dualstack';
191 }
192 }
193 if (!empty($variantTags)) {
194 if (isset($data['variants'])) {
195 foreach ($data['variants'] as $variant) {
196 if (\array_count_values($variant['tags']) == \array_count_values($variantTags)) {
197 return $variant;
198 }
199 }
200 }
201 if (isset($this->data['defaults']['variants'])) {
202 foreach ($this->data['defaults']['variants'] as $variant) {
203 if (\array_count_values($variant['tags']) == \array_count_values($variantTags)) {
204 return $variant;
205 }
206 }
207 }
208 }
209 }
210 }
211