Aws-sdk-php: S3 copyObject does not keep public ACL

Created on 16 Oct 2014  路  4Comments  路  Source: aws/aws-sdk-php

Hi.

I am not sure if this is a bug but i expected this behavior because other object data is copied. Please if i am wrong, is it documented what object data is not copied?

This is the code i use to test it:

<?php

// Upload a file & copy it using v2.7.0
$bucket = 'my-bucket';
$localFile = '/path/to/local/image.jpg';
$keyOriginal = 'key-original.jpg';
$keyCopy = 'key-copy.jpg';

function debugObject($s3, $bucket, $key)
{
    $object = $s3->getObject(['Bucket' => $bucket, 'Key'    => $key]);
    $objectAcl = $s3->getObjectAcl(['Bucket' => $bucket, 'Key'    => $key]);
    $publicGrant = array_filter($objectAcl['Grants'], function ($element) {
        return array_key_exists('URI', $element['Grantee']) &&
            $element['Grantee']['URI'] === 'http://acs.amazonaws.com/groups/global/AllUsers' &&
            $element['Permission'] === 'READ';
    });
    $isPublic = count($publicGrant) === 1;

    echo $key . ': ' . $object['ContentLength'] . ' - ' . $object['CacheControl'] . ' - ' .
        $object['Expires'] . ' - ' . $object['ContentType'] . ' - ' .
        json_encode($object['Metadata']) . ' - ' .
        ($isPublic ? 'public' : 'private') . "\n";
}

$s3->putObject([
    'Bucket' => $bucket,
    'Key'    => $keyOriginal,
    'SourceFile'   => $localFile,
    'ACL' => 'public-read',
    'CacheControl' => 'max-age=1800',
    'Expires' => '1',
    'Metadata'     => [
        'param1' => 'value1',
        'param2' => 'value2'
    ]
]);
debugObject($s3, $bucket, $keyOriginal);

$s3->copyObject([
    'Bucket'     => $bucket,
    'Key'        => $keyCopy,
    'CopySource' => "{$bucket}/{$keyOriginal}"
]);
debugObject($s3, $bucket, $keyCopy);

And the output:

key-orig.jpg: 27599 - max-age=1800 - Thu, 01 Jan 1970 00:00:01 GMT - image/jpeg - {"param1":"value1","param2":"value2"} - public
key-copy.jpg: 27599 - max-age=1800 - Thu, 01 Jan 1970 00:00:01 GMT - image/jpeg - {"param1":"value1","param2":"value2"} - private

Regards,
Armando

guidance

Most helpful comment

Hey Armando, thanks for the detailed bug report! :smile:

I made sure to double check the S3 object copy docs, and this is not an actual bug. The docs say:

When copying an object, you can preserve most of the metadata (default) or specify new metadata. However, the ACL is not preserved and is set to private for the user making the request.

So, with that in mind, you can just add 'ACL' to your CopyObject request.

$s3->copyObject([
    'Bucket'     => $bucket,
    'Key'        => $keyCopy,
    'CopySource' => "{$bucket}/{$keyOriginal}",
    'ACL'        => 'public-read'
]);

All 4 comments

Hey Armando, thanks for the detailed bug report! :smile:

I made sure to double check the S3 object copy docs, and this is not an actual bug. The docs say:

When copying an object, you can preserve most of the metadata (default) or specify new metadata. However, the ACL is not preserved and is set to private for the user making the request.

So, with that in mind, you can just add 'ACL' to your CopyObject request.

$s3->copyObject([
    'Bucket'     => $bucket,
    'Key'        => $keyCopy,
    'CopySource' => "{$bucket}/{$keyOriginal}",
    'ACL'        => 'public-read'
]);

Closing as "no-issue", but please reopen if you need additional help. Thanks.

Thanks for clarifying and the quick response!

We are using a library (FlySystem) and found this behavior using the "rename" & "copy" methods, but we can not set any additional options (so the object is always copied as private). So we decide to investigate first this great SDK and clarify it it was a bug or not. Now we will ask for support to the FlySystem team, or look for workarounds.

Regards,
Armando

No problem! FlySystem is a pretty cool library, but it's definitely a tough job to handle all of the little edge cases in each of the adapters. @FrenkyNet, the FlySystem author, knows where to find me though, if he needs help with any S3 questions.

Was this page helpful?
0 / 5 - 0 ratings