tpyo / amazon-s3-php-class

A standalone Amazon S3 (REST) client for PHP 5/CURL
1.03k stars 504 forks source link

ListBuckets does not work on non-amazon services #171

Open SeventhCycle opened 4 years ago

SeventhCycle commented 4 years ago

Here is an code example that I have here while trying to connect to Linode's S3 cloud storage service:

    require 'includes/S3.php';
    ini_set("display_errors", "on");
    error_reporting(E_ALL);

    $AccessKey = "[REMOVED]"; //private info
    $SecretKey = "[REMOVED]"; //private info
    $EndPoint  = "us-east-1.linodeobjects.com";
    $Region = "us-east-1";

    $s3Client = new S3($AccessKey, $SecretKey);                 
    if (isset($EndPoint)) $s3Client->setEndPoint($EndPoint);
    if (isset($Region)) $s3Client->setRegion($Region);
    $s3Client->setSSL(true);

    $buckets = $s3Client->listBuckets();

As a result, I get this error: Warning: S3::listBuckets(): [403] Unexpected HTTP status in includes/S3.php on line 440

If I go into the file and print out the $rest object to get more information, I get:

stdClass Object
(
    [error] => 
    [body] => SimpleXMLElement Object
        (
            [Code] => SignatureDoesNotMatch
            [RequestId] => tx00000000000000471bbb4-005f306dbc-158bf75-default
            [HostId] => 158bf75-default-default
        )

    [headers] => Array
        (
            [date] => 1597009340
            [type] => application/xml
            [size] => 200
        )

    [code] => 403
)

On the other hand, if I change the above code to an amazon service:

    $AccessKey = "[REMOVED]";
    $SecretKey = "[REMOVED]";
    $EndPoint = "s3.amazonaws.com";
    $Region = "us-east-1";

Authentication works properly on Amazon's services.

Just to make sure this isn't a problem on Linode's end, I tried doing this on another third party (MojoCloud) and ran into the same issue.

Finally, just to make sure that the information is correct, I tried using aws-sdk-php beneath the tpyo library to see if I can connect to S3 using the same info:

    $credentials = new Aws\Credentials\Credentials($AccessKey, $SecretKey);

    $s3Client = new Aws\S3\S3Client([
        'region' => $Region,
        'version' => 'latest',
        'endpoint' => "https://" . $EndPoint,
        'credentials' => $credentials
        ]);

    $result = $s3Client->listBuckets();

    echo "<PRE>";
    print_r($result["Buckets"]);
    exit;

And sure enough, this works for all three services (Amazon, MojoCloud, Linode). This way, I know the connection information is correct.

What I suspect here is a generalization problem with __getSignatureV4() where a valid signature is generated on amazon services, but not on non-amazon services.

Please let me know if any more information is needed here. If any of the maintainers here needs an access key / secret key to try troubleshooting this and debugging this on Linode's object service, please let me know.

Or if there's something obvious I'm missing, please let me know :)

Conver commented 4 years ago

I have the same problem, just with the deleteObject function, I also get the SignatureDoesNotMatch and I'm using DigitalOcean spaces

Conver commented 4 years ago

@tpyo - Can you please take a look at this?

Conver commented 4 years ago

Just odd that putObejct works fine, but not deleteObejct

mblint-postcron commented 4 years ago

Hello guys, I'm facing the same issue, using Linode Object Storage

Conver commented 4 years ago

I really hope it will be fixed, would hate begin using other overloaded classes just for that.

mblint-postcron commented 4 years ago

Hello guys! I could make it work using the v2 signature:

$s3 = new S3();
$s3->setAuth(AWS_S3_KEY, AWS_S3_SECRET);
$s3->setRegion(AWS_S3_REGION);
$s3->setEndpoint(AWS_S3_URL);
$s3->setSignatureVersion('v4');

// Uploader working with v4
$response = S3::putObject(foo,foo,foo);

// List working with v2
S3::setSignatureVersion('v2');
$list = $s3->listBuckets(true);

echo '<pre>';
print_r($list);
die;

I'm kind of new to the amazon s3 service, and I'm making a few tests in order to integrate it to a Legacy PHP application, so this class is really useful for me, any help/improvements will be really appreciated, I can collaborate also :)

Conver commented 4 years ago

Awesome @mblint-postcron, I'll test this in a bit (Using Digital Ocean spaces) and return back to you if it works for me too

Conver commented 4 years ago

@mblint-postcron, where do you see this $s3->setSignatureVersion('v4') function?

I can't find this function or one alike in the class?

Conver commented 4 years ago

@mblint-postcron, hmm.. I don't get where you find this function.

Conver commented 4 years ago

@mblint-postcron You there?

mblint-postcron commented 4 years ago

Hi @Conver, sorry I was OOO. You are right, this method is missing here in this S3 class. I don't know where I find this S3 file now, but seems to be a forked version maybe, check that:

https://gist.github.com/mblint-postcron/d54f6785df3dbeeb955bdd3d901c7127

Let me know if it's working with the v2

Conver commented 4 years ago

Thanks @mblint-postcron, it works perfectly now with the v2 version!

Thanks a lot.