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 / S3 / BucketEndpointArnMiddleware.php
transferito / vendor / aws / aws-sdk-php / src / S3 Last commit date
Crypto 11 months ago Exception 11 months ago RegionalEndpoint 11 months ago UseArnRegion 11 months ago AmbiguousSuccessParser.php 11 months ago ApplyChecksumMiddleware.php 11 months ago BatchDelete.php 11 months ago BucketEndpointArnMiddleware.php 11 months ago BucketEndpointMiddleware.php 11 months ago CalculatesChecksumTrait.php 11 months ago EndpointRegionHelperTrait.php 11 months ago GetBucketLocationParser.php 11 months ago MultipartCopy.php 11 months ago MultipartUploader.php 11 months ago MultipartUploadingTrait.php 11 months ago ObjectCopier.php 11 months ago ObjectUploader.php 11 months ago PermanentRedirectMiddleware.php 11 months ago PostObject.php 11 months ago PostObjectV4.php 11 months ago PutObjectUrlMiddleware.php 11 months ago RetryableMalformedResponseParser.php 11 months ago S3Client.php 11 months ago S3ClientInterface.php 11 months ago S3ClientTrait.php 11 months ago S3EndpointMiddleware.php 11 months ago S3MultiRegionClient.php 11 months ago S3UriParser.php 11 months ago SSECMiddleware.php 11 months ago StreamWrapper.php 11 months ago Transfer.php 11 months ago ValidateResponseChecksumParser.php 11 months ago
BucketEndpointArnMiddleware.php
356 lines
1 <?php
2 namespace Aws\S3;
3
4 use Aws\Api\Service;
5 use Aws\Arn\AccessPointArnInterface;
6 use Aws\Arn\ArnParser;
7 use Aws\Arn\ObjectLambdaAccessPointArn;
8 use Aws\Arn\Exception\InvalidArnException;
9 use Aws\Arn\AccessPointArn as BaseAccessPointArn;
10 use Aws\Arn\S3\OutpostsAccessPointArn;
11 use Aws\Arn\S3\MultiRegionAccessPointArn;
12 use Aws\Arn\S3\OutpostsArnInterface;
13 use Aws\CommandInterface;
14 use Aws\Endpoint\PartitionEndpointProvider;
15 use Aws\Exception\InvalidRegionException;
16 use Aws\Exception\UnresolvedEndpointException;
17 use Aws\S3\Exception\S3Exception;
18 use InvalidArgumentException;
19 use Psr\Http\Message\RequestInterface;
20
21 /**
22 * Checks for access point ARN in members targeting BucketName, modifying
23 * endpoint as appropriate
24 *
25 * @internal
26 */
27 class BucketEndpointArnMiddleware
28 {
29 use EndpointRegionHelperTrait;
30
31 /** @var callable */
32 private $nextHandler;
33
34 /** @var array */
35 private $nonArnableCommands = ['CreateBucket'];
36
37 /** @var boolean */
38 private $isUseEndpointV2;
39
40 /**
41 * Create a middleware wrapper function.
42 *
43 * @param Service $service
44 * @param $region
45 * @param array $config
46 * @return callable
47 */
48 public static function wrap(
49 Service $service,
50 $region,
51 array $config,
52 $isUseEndpointV2
53 ) {
54 return function (callable $handler) use ($service, $region, $config, $isUseEndpointV2) {
55 return new self($handler, $service, $region, $config, $isUseEndpointV2);
56 };
57 }
58
59 public function __construct(
60 callable $nextHandler,
61 Service $service,
62 $region,
63 array $config = [],
64 $isUseEndpointV2 = false
65 ) {
66 $this->partitionProvider = PartitionEndpointProvider::defaultProvider();
67 $this->region = $region;
68 $this->service = $service;
69 $this->config = $config;
70 $this->nextHandler = $nextHandler;
71 $this->isUseEndpointV2 = $isUseEndpointV2;
72 }
73
74 public function __invoke(CommandInterface $cmd, RequestInterface $req)
75 {
76 $nextHandler = $this->nextHandler;
77
78 $op = $this->service->getOperation($cmd->getName())->toArray();
79 if (!empty($op['input']['shape'])) {
80 $service = $this->service->toArray();
81 if (!empty($input = $service['shapes'][$op['input']['shape']])) {
82 foreach ($input['members'] as $key => $member) {
83 if ($member['shape'] === 'BucketName') {
84 $arnableKey = $key;
85 break;
86 }
87 }
88
89 if (!empty($arnableKey) && ArnParser::isArn($cmd[$arnableKey])) {
90
91 try {
92 // Throw for commands that do not support ARN inputs
93 if (in_array($cmd->getName(), $this->nonArnableCommands)) {
94 throw new S3Exception(
95 'ARN values cannot be used in the bucket field for'
96 . ' the ' . $cmd->getName() . ' operation.',
97 $cmd
98 );
99 }
100
101 if (!$this->isUseEndpointV2) {
102 $arn = ArnParser::parse($cmd[$arnableKey]);
103 $partition = $this->validateArn($arn);
104 $host = $this->generateAccessPointHost($arn, $req);
105 }
106 // Remove encoded bucket string from path
107 $path = $req->getUri()->getPath();
108 $encoded = rawurlencode($cmd[$arnableKey]);
109 $len = strlen($encoded) + 1;
110 if (trim(substr($path, 0, $len), '/') === "{$encoded}") {
111 $path = substr($path, $len);
112 if (substr($path, 0, 1) !== "/") {
113 $path = '/' . $path;
114 }
115 }
116 if (empty($path)) {
117 $path = '';
118 }
119
120 // Set modified request
121 if ($this->isUseEndpointV2) {
122 $req = $req->withUri(
123 $req->getUri()->withPath($path)
124
125 );
126 goto next;
127 }
128
129 $req = $req->withUri(
130 $req->getUri()->withPath($path)->withHost($host)
131 );
132
133 // Update signing region based on ARN data if configured to do so
134 if ($this->config['use_arn_region']->isUseArnRegion()
135 && !$this->config['use_fips_endpoint']->isUseFipsEndpoint()
136 ) {
137 $region = $arn->getRegion();
138 } else {
139 $region = $this->region;
140 }
141 $endpointData = $partition([
142 'region' => $region,
143 'service' => $arn->getService()
144 ]);
145 $cmd['@context']['signing_region'] = $endpointData['signingRegion'];
146
147 // Update signing service for Outposts and Lambda ARNs
148 if ($arn instanceof OutpostsArnInterface
149 || $arn instanceof ObjectLambdaAccessPointArn
150 ) {
151 $cmd['@context']['signing_service'] = $arn->getService();
152 }
153 } catch (InvalidArnException $e) {
154 // Add context to ARN exception
155 throw new S3Exception(
156 'Bucket parameter parsed as ARN and failed with: '
157 . $e->getMessage(),
158 $cmd,
159 [],
160 $e
161 );
162 }
163 }
164 }
165 }
166 next:
167 return $nextHandler($cmd, $req);
168 }
169
170
171 private function generateAccessPointHost(
172 BaseAccessPointArn $arn,
173 RequestInterface $req
174 ) {
175 if ($arn instanceof OutpostsAccessPointArn) {
176 $accesspointName = $arn->getAccesspointName();
177 } else {
178 $accesspointName = $arn->getResourceId();
179 }
180
181 if ($arn instanceof MultiRegionAccessPointArn) {
182 $partition = $this->partitionProvider->getPartitionByName(
183 $arn->getPartition(),
184 's3'
185 );
186 $dnsSuffix = $partition->getDnsSuffix();
187 return "{$accesspointName}.accesspoint.s3-global.{$dnsSuffix}";
188 }
189
190 $host = "{$accesspointName}-" . $arn->getAccountId();
191
192 $useFips = $this->config['use_fips_endpoint']->isUseFipsEndpoint();
193 $fipsString = $useFips ? "-fips" : "";
194
195 if ($arn instanceof OutpostsAccessPointArn) {
196 $host .= '.' . $arn->getOutpostId() . '.s3-outposts';
197 } else if ($arn instanceof ObjectLambdaAccessPointArn) {
198 if (!empty($this->config['endpoint'])) {
199 return $host . '.' . $this->config['endpoint'];
200 } else {
201 $host .= ".s3-object-lambda{$fipsString}";
202 }
203 } else {
204 $host .= ".s3-accesspoint{$fipsString}";
205 if (!empty($this->config['dual_stack'])) {
206 $host .= '.dualstack';
207 }
208 }
209
210 if (!empty($this->config['use_arn_region']->isUseArnRegion())) {
211 $region = $arn->getRegion();
212 } else {
213 $region = $this->region;
214 }
215 $region = \Aws\strip_fips_pseudo_regions($region);
216 $host .= '.' . $region . '.' . $this->getPartitionSuffix($arn, $this->partitionProvider);
217 return $host;
218 }
219
220 /**
221 * Validates an ARN, returning a partition object corresponding to the ARN
222 * if successful
223 *
224 * @param $arn
225 * @return \Aws\Endpoint\Partition
226 */
227 private function validateArn($arn)
228 {
229 if ($arn instanceof AccessPointArnInterface) {
230
231 // Dualstack is not supported with Outposts access points
232 if ($arn instanceof OutpostsAccessPointArn
233 && !empty($this->config['dual_stack'])
234 ) {
235 throw new UnresolvedEndpointException(
236 'Dualstack is currently not supported with S3 Outposts access'
237 . ' points. Please disable dualstack or do not supply an'
238 . ' access point ARN.');
239 }
240 if ($arn instanceof MultiRegionAccessPointArn) {
241 if (!empty($this->config['disable_multiregion_access_points'])) {
242 throw new UnresolvedEndpointException(
243 'Multi-Region Access Point ARNs are disabled, but one was provided. Please'
244 . ' enable them or provide a different ARN.'
245 );
246 }
247 if (!empty($this->config['dual_stack'])) {
248 throw new UnresolvedEndpointException(
249 'Multi-Region Access Point ARNs do not currently support dual stack. Please'
250 . ' disable dual stack or provide a different ARN.'
251 );
252 }
253 }
254 // Accelerate is not supported with access points
255 if (!empty($this->config['accelerate'])) {
256 throw new UnresolvedEndpointException(
257 'Accelerate is currently not supported with access points.'
258 . ' Please disable accelerate or do not supply an access'
259 . ' point ARN.');
260 }
261
262 // Path-style is not supported with access points
263 if (!empty($this->config['path_style'])) {
264 throw new UnresolvedEndpointException(
265 'Path-style addressing is currently not supported with'
266 . ' access points. Please disable path-style or do not'
267 . ' supply an access point ARN.');
268 }
269
270 // Custom endpoint is not supported with access points
271 if (!is_null($this->config['endpoint'])
272 && !$arn instanceof ObjectLambdaAccessPointArn
273 ) {
274 throw new UnresolvedEndpointException(
275 'A custom endpoint has been supplied along with an access'
276 . ' point ARN, and these are not compatible with each other.'
277 . ' Please only use one or the other.');
278 }
279
280 // Dualstack is not supported with object lambda access points
281 if ($arn instanceof ObjectLambdaAccessPointArn
282 && !empty($this->config['dual_stack'])
283 ) {
284 throw new UnresolvedEndpointException(
285 'Dualstack is currently not supported with Object Lambda access'
286 . ' points. Please disable dualstack or do not supply an'
287 . ' access point ARN.');
288 }
289 // Global endpoints do not support cross-region requests
290 if ($this->isGlobal($this->region)
291 && $this->config['use_arn_region']->isUseArnRegion() == false
292 && $arn->getRegion() != $this->region
293 && !$arn instanceof MultiRegionAccessPointArn
294 ) {
295 throw new UnresolvedEndpointException(
296 'Global endpoints do not support cross region requests.'
297 . ' Please enable use_arn_region or do not supply a global region'
298 . ' with a different region in the ARN.');
299 }
300
301 // Get partitions for ARN and client region
302 $arnPart = $this->partitionProvider->getPartition(
303 $arn->getRegion(),
304 's3'
305 );
306 $clientPart = $this->partitionProvider->getPartition(
307 $this->region,
308 's3'
309 );
310
311 // If client partition not found, try removing pseudo-region qualifiers
312 if (!($clientPart->isRegionMatch($this->region, 's3'))) {
313 $clientPart = $this->partitionProvider->getPartition(
314 \Aws\strip_fips_pseudo_regions($this->region),
315 's3'
316 );
317 }
318 if (!$arn instanceof MultiRegionAccessPointArn) {
319 // Verify that the partition matches for supplied partition and region
320 if ($arn->getPartition() !== $clientPart->getName()) {
321 throw new InvalidRegionException('The supplied ARN partition'
322 . " does not match the client's partition.");
323 }
324 if ($clientPart->getName() !== $arnPart->getName()) {
325 throw new InvalidRegionException('The corresponding partition'
326 . ' for the supplied ARN region does not match the'
327 . " client's partition.");
328 }
329
330 // Ensure ARN region matches client region unless
331 // configured for using ARN region over client region
332 $this->validateMatchingRegion($arn);
333
334 // Ensure it is not resolved to fips pseudo-region for S3 Outposts
335 $this->validateFipsConfigurations($arn);
336 }
337
338 return $arnPart;
339 }
340
341 throw new InvalidArnException('Provided ARN was not a valid S3 access'
342 . ' point ARN or S3 Outposts access point ARN.');
343 }
344
345 /**
346 * Checks if a region is global
347 *
348 * @param $region
349 * @return bool
350 */
351 private function isGlobal($region)
352 {
353 return $region == 's3-external-1' || $region == 'aws-global';
354 }
355 }
356