| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 | 
							- <?php
 
- namespace Aws\S3;
 
- use Aws\Api\Service;
 
- use Aws\Arn\AccessPointArnInterface;
 
- use Aws\Arn\ArnParser;
 
- use Aws\Arn\ObjectLambdaAccessPointArn;
 
- use Aws\Arn\Exception\InvalidArnException;
 
- use Aws\Arn\AccessPointArn as BaseAccessPointArn;
 
- use Aws\Arn\S3\OutpostsAccessPointArn;
 
- use Aws\Arn\S3\MultiRegionAccessPointArn;
 
- use Aws\Arn\S3\OutpostsArnInterface;
 
- use Aws\CommandInterface;
 
- use Aws\Endpoint\PartitionEndpointProvider;
 
- use Aws\Exception\InvalidRegionException;
 
- use Aws\Exception\UnresolvedEndpointException;
 
- use Aws\S3\Exception\S3Exception;
 
- use InvalidArgumentException;
 
- use Psr\Http\Message\RequestInterface;
 
- /**
 
-  * Checks for access point ARN in members targeting BucketName, modifying
 
-  * endpoint as appropriate
 
-  *
 
-  * @internal
 
-  */
 
- class BucketEndpointArnMiddleware
 
- {
 
-     use EndpointRegionHelperTrait;
 
-     /** @var callable */
 
-     private $nextHandler;
 
-     /** @var array */
 
-     private $nonArnableCommands = ['CreateBucket'];
 
-     /** @var boolean */
 
-     private $isUseEndpointV2;
 
-     /**
 
-      * Create a middleware wrapper function.
 
-      *
 
-      * @param Service $service
 
-      * @param $region
 
-      * @param array $config
 
-      * @return callable
 
-      */
 
-     public static function wrap(
 
-         Service $service,
 
-         $region,
 
-         array $config,
 
-         $isUseEndpointV2
 
-     ) {
 
-         return function (callable $handler) use ($service, $region, $config, $isUseEndpointV2) {
 
-             return new self($handler, $service, $region, $config, $isUseEndpointV2);
 
-         };
 
-     }
 
-     public function __construct(
 
-         callable $nextHandler,
 
-         Service $service,
 
-         $region,
 
-         array $config = [],
 
-         $isUseEndpointV2 = false
 
-     ) {
 
-         $this->partitionProvider = PartitionEndpointProvider::defaultProvider();
 
-         $this->region = $region;
 
-         $this->service = $service;
 
-         $this->config = $config;
 
-         $this->nextHandler = $nextHandler;
 
-         $this->isUseEndpointV2 = $isUseEndpointV2;
 
-     }
 
-     public function __invoke(CommandInterface $cmd, RequestInterface $req)
 
-     {
 
-         $nextHandler = $this->nextHandler;
 
-         $op = $this->service->getOperation($cmd->getName())->toArray();
 
-         if (!empty($op['input']['shape'])) {
 
-             $service = $this->service->toArray();
 
-             if (!empty($input = $service['shapes'][$op['input']['shape']])) {
 
-                 foreach ($input['members'] as $key => $member) {
 
-                     if ($member['shape'] === 'BucketName') {
 
-                         $arnableKey = $key;
 
-                         break;
 
-                     }
 
-                 }
 
-                 if (!empty($arnableKey) && ArnParser::isArn($cmd[$arnableKey])) {
 
-                     try {
 
-                         // Throw for commands that do not support ARN inputs
 
-                         if (in_array($cmd->getName(), $this->nonArnableCommands)) {
 
-                             throw new S3Exception(
 
-                                 'ARN values cannot be used in the bucket field for'
 
-                                 . ' the ' . $cmd->getName() . ' operation.',
 
-                                 $cmd
 
-                             );
 
-                         }
 
-                         if (!$this->isUseEndpointV2) {
 
-                             $arn = ArnParser::parse($cmd[$arnableKey]);
 
-                             $partition = $this->validateArn($arn);
 
-                             $host = $this->generateAccessPointHost($arn, $req);
 
-                         }
 
-                         // Remove encoded bucket string from path
 
-                         $path = $req->getUri()->getPath();
 
-                         $encoded = rawurlencode($cmd[$arnableKey]);
 
-                         $len = strlen($encoded) + 1;
 
-                         if (trim(substr($path, 0, $len), '/') === "{$encoded}") {
 
-                             $path = substr($path, $len);
 
-                             if (substr($path, 0, 1) !== "/") {
 
-                                 $path = '/' . $path;
 
-                             }
 
-                         }
 
-                         if (empty($path)) {
 
-                             $path = '';
 
-                         }
 
-                         // Set modified request
 
-                         if ($this->isUseEndpointV2) {
 
-                             $req = $req->withUri(
 
-                                 $req->getUri()->withPath($path)
 
-                             );
 
-                             goto next;
 
-                         }
 
-                         $req = $req->withUri(
 
-                             $req->getUri()->withPath($path)->withHost($host)
 
-                         );
 
-                         // Update signing region based on ARN data if configured to do so
 
-                         if ($this->config['use_arn_region']->isUseArnRegion()
 
-                             && !$this->config['use_fips_endpoint']->isUseFipsEndpoint()
 
-                         ) {
 
-                             $region = $arn->getRegion();
 
-                         } else {
 
-                             $region = $this->region;
 
-                         }
 
-                         $endpointData = $partition([
 
-                             'region' => $region,
 
-                             'service' => $arn->getService()
 
-                         ]);
 
-                         $cmd['@context']['signing_region'] = $endpointData['signingRegion'];
 
-                         // Update signing service for Outposts and Lambda ARNs
 
-                         if ($arn instanceof OutpostsArnInterface
 
-                             || $arn instanceof ObjectLambdaAccessPointArn
 
-                         ) {
 
-                             $cmd['@context']['signing_service'] = $arn->getService();
 
-                         }
 
-                     } catch (InvalidArnException $e) {
 
-                         // Add context to ARN exception
 
-                         throw new S3Exception(
 
-                             'Bucket parameter parsed as ARN and failed with: '
 
-                             . $e->getMessage(),
 
-                             $cmd,
 
-                             [],
 
-                             $e
 
-                         );
 
-                     }
 
-                 }
 
-             }
 
-         }
 
-         next:
 
-             return $nextHandler($cmd, $req);
 
-     }
 
-     private function generateAccessPointHost(
 
-         BaseAccessPointArn $arn,
 
-         RequestInterface $req
 
-     ) {
 
-         if ($arn instanceof OutpostsAccessPointArn) {
 
-             $accesspointName = $arn->getAccesspointName();
 
-         } else {
 
-             $accesspointName = $arn->getResourceId();
 
-         }
 
-         if ($arn instanceof MultiRegionAccessPointArn) {
 
-             $partition = $this->partitionProvider->getPartitionByName(
 
-                 $arn->getPartition(),
 
-                 's3'
 
-             );
 
-             $dnsSuffix = $partition->getDnsSuffix();
 
-             return "{$accesspointName}.accesspoint.s3-global.{$dnsSuffix}";
 
-         }
 
-         $host = "{$accesspointName}-" . $arn->getAccountId();
 
-         $useFips = $this->config['use_fips_endpoint']->isUseFipsEndpoint();
 
-         $fipsString = $useFips ? "-fips" : "";
 
-         if ($arn instanceof OutpostsAccessPointArn) {
 
-             $host .= '.' . $arn->getOutpostId() . '.s3-outposts';
 
-         } else if ($arn instanceof ObjectLambdaAccessPointArn) {
 
-             if (!empty($this->config['endpoint'])) {
 
-                 return $host . '.' . $this->config['endpoint'];
 
-             } else {
 
-                 $host .= ".s3-object-lambda{$fipsString}";
 
-             }
 
-         } else {
 
-             $host .= ".s3-accesspoint{$fipsString}";
 
-             if (!empty($this->config['dual_stack'])) {
 
-                 $host .= '.dualstack';
 
-             }
 
-         }
 
-         if (!empty($this->config['use_arn_region']->isUseArnRegion())) {
 
-             $region = $arn->getRegion();
 
-         } else {
 
-             $region = $this->region;
 
-         }
 
-         $region = \Aws\strip_fips_pseudo_regions($region);
 
-         $host .= '.' . $region . '.' . $this->getPartitionSuffix($arn, $this->partitionProvider);
 
-         return $host;
 
-     }
 
-     /**
 
-      * Validates an ARN, returning a partition object corresponding to the ARN
 
-      * if successful
 
-      *
 
-      * @param $arn
 
-      * @return \Aws\Endpoint\Partition
 
-      */
 
-     private function validateArn($arn)
 
-     {
 
-         if ($arn instanceof AccessPointArnInterface) {
 
-             // Dualstack is not supported with Outposts access points
 
-             if ($arn instanceof OutpostsAccessPointArn
 
-                 && !empty($this->config['dual_stack'])
 
-             ) {
 
-                 throw new UnresolvedEndpointException(
 
-                     'Dualstack is currently not supported with S3 Outposts access'
 
-                     . ' points. Please disable dualstack or do not supply an'
 
-                     . ' access point ARN.');
 
-             }
 
-             if ($arn instanceof MultiRegionAccessPointArn) {
 
-                 if (!empty($this->config['disable_multiregion_access_points'])) {
 
-                     throw new UnresolvedEndpointException(
 
-                         'Multi-Region Access Point ARNs are disabled, but one was provided.  Please'
 
-                         . ' enable them or provide a different ARN.'
 
-                     );
 
-                 }
 
-                 if (!empty($this->config['dual_stack'])) {
 
-                     throw new UnresolvedEndpointException(
 
-                         'Multi-Region Access Point ARNs do not currently support dual stack. Please'
 
-                         . ' disable dual stack or provide a different ARN.'
 
-                     );
 
-                 }
 
-             }
 
-             // Accelerate is not supported with access points
 
-             if (!empty($this->config['accelerate'])) {
 
-                 throw new UnresolvedEndpointException(
 
-                     'Accelerate is currently not supported with access points.'
 
-                     . ' Please disable accelerate or do not supply an access'
 
-                     . ' point ARN.');
 
-             }
 
-             // Path-style is not supported with access points
 
-             if (!empty($this->config['path_style'])) {
 
-                 throw new UnresolvedEndpointException(
 
-                     'Path-style addressing is currently not supported with'
 
-                     . ' access points. Please disable path-style or do not'
 
-                     . ' supply an access point ARN.');
 
-             }
 
-             // Custom endpoint is not supported with access points
 
-             if (!is_null($this->config['endpoint'])
 
-                 && !$arn instanceof  ObjectLambdaAccessPointArn
 
-             ) {
 
-                 throw new UnresolvedEndpointException(
 
-                     'A custom endpoint has been supplied along with an access'
 
-                     . ' point ARN, and these are not compatible with each other.'
 
-                     . ' Please only use one or the other.');
 
-             }
 
-             // Dualstack is not supported with object lambda access points
 
-             if ($arn instanceof ObjectLambdaAccessPointArn
 
-                 && !empty($this->config['dual_stack'])
 
-             ) {
 
-                 throw new UnresolvedEndpointException(
 
-                     'Dualstack is currently not supported with Object Lambda access'
 
-                     . ' points. Please disable dualstack or do not supply an'
 
-                     . ' access point ARN.');
 
-             }
 
-             // Global endpoints do not support cross-region requests
 
-             if ($this->isGlobal($this->region)
 
-                 && $this->config['use_arn_region']->isUseArnRegion() == false
 
-                 && $arn->getRegion() != $this->region
 
-                 && !$arn instanceof MultiRegionAccessPointArn
 
-             ) {
 
-                 throw new UnresolvedEndpointException(
 
-                     'Global endpoints do not support cross region requests.'
 
-                     . ' Please enable use_arn_region or do not supply a global region'
 
-                     . ' with a different region in the ARN.');
 
-             }
 
-             // Get partitions for ARN and client region
 
-             $arnPart = $this->partitionProvider->getPartition(
 
-                 $arn->getRegion(),
 
-                 's3'
 
-             );
 
-             $clientPart = $this->partitionProvider->getPartition(
 
-                 $this->region,
 
-                 's3'
 
-             );
 
-             // If client partition not found, try removing pseudo-region qualifiers
 
-             if (!($clientPart->isRegionMatch($this->region, 's3'))) {
 
-                 $clientPart = $this->partitionProvider->getPartition(
 
-                     \Aws\strip_fips_pseudo_regions($this->region),
 
-                     's3'
 
-                 );
 
-             }
 
-             if (!$arn instanceof MultiRegionAccessPointArn) {
 
-                 // Verify that the partition matches for supplied partition and region
 
-                 if ($arn->getPartition() !== $clientPart->getName()) {
 
-                     throw new InvalidRegionException('The supplied ARN partition'
 
-                         . " does not match the client's partition.");
 
-                 }
 
-                 if ($clientPart->getName() !== $arnPart->getName()) {
 
-                     throw new InvalidRegionException('The corresponding partition'
 
-                         . ' for the supplied ARN region does not match the'
 
-                         . " client's partition.");
 
-                 }
 
-                 // Ensure ARN region matches client region unless
 
-                 // configured for using ARN region over client region
 
-                 $this->validateMatchingRegion($arn);
 
-                 // Ensure it is not resolved to fips pseudo-region for S3 Outposts
 
-                 $this->validateFipsConfigurations($arn);
 
-             }
 
-             return $arnPart;
 
-         }
 
-         throw new InvalidArnException('Provided ARN was not a valid S3 access'
 
-             . ' point ARN or S3 Outposts access point ARN.');
 
-     }
 
-     /**
 
-      * Checks if a region is global
 
-      *
 
-      * @param $region
 
-      * @return bool
 
-      */
 
-     private function isGlobal($region)
 
-     {
 
-         return $region == 's3-external-1' || $region == 'aws-global';
 
-     }
 
- }
 
 
  |