Add metadata to S3 Object, while keeping existing metadata and ACL
Asked Answered
M

0

6

I'm looking for a way to programmatically add specific metadata to a set of S3 objects. I've recently updated the code in my project to set the 'Cache-Control: max-age' and 'Expires' when uploading objects to S3, but now I'm trying to set those values for my existing S3 objects. I don't want anything else to change, such as the ACL or any other metadata.

I had tried using the AWS CLI to achieve this, but run into a couple issues. My bucket has both public and non-public objects, so I cannot just set the acl to 'public-read'. I want the ACL to remain unchanged, but if I set nothing, they all become private. Also, I want to add metadata, but keep any existing metadata intact. Here's the cli call I had tried:

aws s3 cp s3://my-bucket s3://my-bucket --acl public-read --recursive --metadata-directive=REPLACE --cache-control max-age=2592000 --expires 'Wed, 29 July 2020 00:00:01 GMT'

I am using the AWS PHP SDK, but am open to other methods.

For maintaining the same metadata, I've tried using headObject to get existing header data... but it give back a lot of values. I can iterate over them, but I don't know which ones I'd need to set again to maintain everything.

For maintaining the same ACL, I have tried using getObjectAcl followed by putObjectAcl... but I'm pretty sure this isn't going to work in all cases (I'm pretty sure my logic for setting the ACL value as public-read or private isn't robust enough for all cases...).

$acl_result = $s3->getObjectAcl([
    'Bucket' => $bucket,
    'Key' => $object_key
]);

$grants = $acl_result->get('Grants');
$owner = $acl_result->get('Owner');

...

$public = false;
foreach($grants as $grant){
    if(isset($grant['Grantee']['URI'])
        && $grant['Grantee']['URI'] == 'http://acs.amazonaws.com/groups/global/AllUsers'
        && $grant['Permission'] == 'READ'){
        $public = true;
    }
}
$object = [
    'Bucket' => $bucket,
    'Key'    => $object_key,
    'ACL'    => ($public ? 'public-read' : 'private'),
    'AccessControlPolicy'    => [
        'Owner' => $owner,
        'Grants' => $grants,
    ],
];
$s3->putObjectAcl($object);

Any help is appreciated. Thanks!

Mailemailed answered 30/6, 2020 at 15:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.