rakk7/directo

A library to generate signatures for direct upload to Amazon S3

v0.3 2019-09-12 04:17 UTC

This package is auto-updated.

Last update: 2024-09-12 18:28:50 UTC


README

A library to generate AWS Signature V4 and supplement form inputs, for direct upload to Amazon S3. Includes a bridge to Laravel as-well.

Install

$ composer require kfirba/directo

Prerequisites - CORS & Bucket Policy

In order for the upload to succeed and not get denied by Amazon S3 we will need to configure the CORS option and the bucket policy.

To update the CORS and the bucket policy, log in to your AWS account and go to S3. Now select your bucket and click Properties on the top-right corner. Click on Permissions.

To update the CORS configuration, click the Edit CORS Configuration button. I recommend the following CORS configuration:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

To update the bucket policy, click the Edit bucket policy button. I recommend the following bucket policy:

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Principal": "*",
			"Action": [
				"s3:PutObject",
				"s3:PutObjectAcl"
			],
			"Resource": "arn:aws:s3:::BUCKET_NAME/*"
		}
	]
}

Don't forget to change BUCKET_NAME to your bucket's name.

Note: If you don't plan to ever upload any file with any other ACL than private, you may want to omit the "s3:PutObjectAcl".

Laravel Users

If you are a Laravel user, the package contains a bridge for you.

Update your app.php providers array and add:

Kfirba\Directo\Support\DirectoServiceProvider::class,

Also, update your aliases array and add:

'Directo' => Kfirba\Directo\Support\Facades\Directo::class,

If you need to change some of the default settings, you can either publish the directo.php config to make the changes global every time you try to generate a signature, or use the convenient setter Directo provides.

$ php artisan vendor:publish --tag=directo

You should now be able to find a directo.php file in your config/ directory with all of the default options.

// You can also change the options on-the-fly
Directo::setOptions(['acl' => 'private'])->inputsAsArray();

The on-the-fly change is useful especially when you may have more than 1 form in your document and one of them may require different options than the other one. For example, a form to upload some private metrics data to S3, you will want to set the acl to private and a form to upload a profile picture which you will want to set the acl to atleast public-read.

The package reads your S3 configurations specified in config/filesystems.php under the disks.s3 array. To change the configs, you can change the following keys in your .env file:

S3_KEY=myS3Key
S3_SECRET=myS3Secret
S3_REGION=eu-central-1
S3_BUCKET=bucket

Laravel then reads these environment variables and set the config in filesystems.disks.s3 which Directo uses.

Usage

use Kfirba\Directo\Directo;

require_once __DIR__ . "/vendor/autoload.php";

$directo = new Directo('bucket', 'region', 'key', 'secret', $options = []);

Then, using the object we've just made, we can generate the form's url and all the needed hidden inputs.

<form action="<?php echo $directo->formUrl()?>" method="post" enctype="multipart/form-data">
    <?php echo $directo->inputsAsHtml() ?>
    
    <input type="file" name="file">
</form>

Laravel Users Usage

If you are using laravel, there is a Directo facade you can use. Also, you can type-hint the Directo class in any auto-resolving class, such as any Controller and it will be automatically resolved.

// Facade:
Directo::formUrl();
Directo::inputsAsHtml();

// Type-hinted
// SomeController.php:

use Kfirba\Directo\Directo;
// ...
public function index(Directo $directo)
{
    dd($directo->signature());
}

Signing a policy

Sometimes, when using file uploader plugin, such as FineUploader, the plugin will send a policy to the server to be signed. Once the policy has been signed, the plugin will submit the policy and the signature to AWS as authentication key.

Directo also offers the ability to sign a given policy. The policy should be either a valid json-encoded policy or a base64-encoded policy (which decodes to a valid json-encoded policy).

If you already have a Directo object, you may simply call the sign() method:

$directo->sign($policy);
// =>
// ['policy' => 'base64-encoded policy...', 'signature => 'the signature...']

If you don't have a Directo object, you may create a new one or use the underlying Signature object:

$signature = new Signature($secret, $region, $policy);

$signature->sign($policy);
// =>
// ['policy' => 'base64-encoded policy...', 'signature => 'the signature...']

The arguments that the Signature object needs are required for generating the SigningKey. The Signature object will parse the given policy and will extract any additional parameters it needs for the SigningKey.

If you are a Laravel user, you can use the Directo facade anywhere:

Directo::sign($policy);
// =>
// ['policy' => 'base64-encoded policy...', 'signature => 'the signature...']

The sign() method returns an array with the following keys:

  1. policy - base64 encoded string of the policy.
  2. signature - the signature for the aforementioned policy.

Options

The options availalbe are:

For example:

$directo = new Directo("bucket", "region", "key", "secret", [
    'acl' => 'private',
    'max_file_size' => 10,
    'additional_inputs' => [
        'Content-Disposition' => 'attachment'
    ]
]);

Available Methods

Thumbs Up 👍

Thanks Edd Turtle for your great article. The purpose of this package is to make the process of signature generating a bit more modular, hence offer additional features, and create a bridge for Laravel users.

License

Directo is open-sourced software licensed under the MIT license.