-
-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[S3] Feature Request: Support S3 Access Points #1450
Comments
did you tried https://async-aws.com/features/presign.html ? |
Sure, here is an example with using async-aws/s3 $client->presign(\AsyncAws\S3\Input\GetObjectRequest::create([
"Bucket" => "arn:aws:s3-object-lambda:eu-central-1:000000000000:accesspoint/thumbnail-generator",
"Key" => "Foo/HappyFace.jpg"
])); Result of async-aws
Result of aws-sdk-php (expected)
*Here is a original aws BucketEndpointArnMiddleware where actually hostname resolves depending on a Bucket |
This is last feature I miss to fully switch to async-aws, so I open for contribution ) |
Kinda MVP with lots of hacks, but generates valid pre-signed url <?php
declare(strict_types=1);
use AsyncAws\Core\Request;
use AsyncAws\Core\RequestContext;
use AsyncAws\Core\Stream\StreamFactory;
use AsyncAws\S3\Signer\SignerV4ForS3;
final class MVP
{
private const ARN_PREFIX = "arn:aws:s3-object-lambda:";
public function __construct(private readonly \AsyncAws\S3\S3Client $client)
{
}
/**
* @param array{
* Bucket: string,
* Key: string,
* ResponseContentDisposition?: string,
* ResponseContentType?: string,
* } $input
*/
public function __invoke(array $input, \DateTimeImmutable $expires): string
{
$this->assertSupports($input["Bucket"]);
[$host, $region] = $this->arnToHost($input["Bucket"]);
$headers = ['content-type' => 'application/xml'];
if (isset($input["ResponseContentDisposition"])) {
$query['response-content-disposition'] = $input["ResponseContentDisposition"];
}
if (isset($input["ResponseContentType"])) {
$query['response-content-type'] = $input["ResponseContentType"];
}
$endpoint = "{$host}/"
. \str_replace('%2F', '/', \rawurlencode(\ltrim($input["Key"], "/")))
. "?"
. \http_build_query($query, '', '&', \PHP_QUERY_RFC3986);
$request = new Request('GET', '', $query, $headers, StreamFactory::create(''));
$request->setEndpoint($endpoint);
$r = new \ReflectionProperty(\AsyncAws\Core\AbstractApi::class, "credentialProvider");
$r->setAccessible(true);
$credentialProvider = $r->getValue($this->client);
if (null !== $credentials = $credentialProvider?->getCredentials($this->client->getConfiguration())) {
$signer = new SignerV4ForS3("s3-object-lambda", $region);
$signer->presign($request, $credentials, new RequestContext(['expirationDate' => $expires]));
}
return $request->getEndpoint();
}
private function assertSupports(string $arn): void
{
if (0 !== \strpos($arn, self::ARN_PREFIX)) {
throw new \LogicException("Only s3-object-lambda can be provided");
}
}
/** @return array{string, string} */
private function arnToHost(string $arn): array
{
$arn = \substr($arn, \strlen(self::ARN_PREFIX));
$parts = \explode(":", $arn, 3);
if (3 !== \count($parts)) {
throw new \LogicException("Invalid s3-object-lambda ARN provided");
}
$region = $parts[0];
$accountId = $parts[1];
$accessPoint = \explode("/", $parts[2], 2)[1] ?? $parts[2];
return ["https://{$accessPoint}-{$accountId}.s3-object-lambda.{$region}.amazonaws.com", $region];
}
} |
Hi @jderusse! Looking forward to your response. Thanks! |
Have you tried using the access endpoint alias instead of it's ARN ? From my quick reading of the documentation links you provided, I think it might work already. |
Thanks for your reply! Looking back to my feature request - it should be converted into support of Access Points (e.g. Outposts, ObjectLambdaAccessPoint, etc.) out of the box. Good idea here to mention in the documentation that currently there is no support of S3 Access Points to avoid further issues and misunderstanding Also, in my scenario with thumbnail generator - I provide a custom query parameter I've made a workaround and created own GetObjectRequest which accepts final class GetObjectRequest extends Input
{
/**
* @param array{
* Bucket?: string,
* Key?: string,
* ...
* CustomQuery?: array<string, string>,
*
* @region?: string,
* } $input
*/
public function __construct(array $input = [])
...
public function request(): Request
{
...
$query += $this->customQuery ?? [];
return new Request('GET', $uriString, $query, $headers, StreamFactory::create($body));
}
} |
Is passing custom query parameters supported by the official SDK ? |
PRs updating the documentation are welcome. |
Unfortunately No :) |
👍 I will create a PR later |
Hey 👋
Official aws-php-sdk supports presign of s3 access points, here is an example
So, the bucket like
arn:aws:s3-object-lambda:eu-central-1:000000000000:accesspoint/<accesspoint-name>
resolves into
https://<accesspoint-name>-000000000000.s3-object-lambda.eu-central-1.amazonaws.com
*Real use-case: s3 lambda func generates a thumbnail by accessing the pre-signed URL
Would be great to have this functionality inside
async-aws
❤️Research:
The text was updated successfully, but these errors were encountered: