Skip to content

Commit

Permalink
Support environment variables in volume settings
Browse files Browse the repository at this point in the history
resolves #35
  • Loading branch information
brandonkelly committed Dec 8, 2018
1 parent bbe8488 commit c65b134
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 26 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

### Added
- Access Key ID, Secret Access Key, Subfolder, and CloudFront Distribution ID settings can now be set to environment variables. ([#35](https://github.com/craftcms/aws-s3/issues/35))

### Changed
- Show validation error when creating a volume and not specify a bucket.

Expand Down
43 changes: 30 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This plugin provides an [Amazon S3](https://aws.amazon.com/s3/) integration for

## Requirements

This plugin requires Craft CMS 3.0.0-RC4 or later.
This plugin requires Craft CMS 3.1.0 or later.


## Installation
Expand Down Expand Up @@ -37,39 +37,56 @@ To create a new asset volume for your Amazon S3 bucket, go to Settings → Asset

### Per-Environment Configuration

Once you’ve created your S3 volume in the Control Panel, you can override its settings with different values for each environment.
Amazon S3 volumes’ Base URL, Access Key ID, Secret Access Key, Subfolder, and CloudFront Distribution ID settings can be set to environment variables.

First, add the following environment variables to your `.env` and `.env.example` files:

```
```bash
# The S3 volume's base URL
S3_BASE_URL=""

# The AWS API key with read/write access to S3
S3_API_KEY=""

# The AWS API key secret
S3_SECRET=""

# The S3 buckte subfolder the volume should be set to
S3_SUBFOLDER=""

# The CloudFront distribution ID the S3 bucket is cached by
S3_CLOUDFRONT_ID=""
```

Fill in the values in your `.env` file (leaving the values in `.env.example` blank).

Then when you create an Amazon S3 volume, you can reference these environment variables in the volume’s setting by typing `$` followed by the environment variable names.

Only the environment variable names will be saved to your database and `project.yaml` file, not their values.

### Overriding the Bucket and Region

Once you’ve created your Amazon S3 volume, you can override its bucket and/or region for an environment by adding two new environment variables:

```bash
# The name of the S3 bucket
S3_BUCKET=""

# The region the S3 bucket is in
S3_REGION=""
```

Then fill in the values in your `.env` file (leaving the values in `.env.example` blank).
```

Finally, create a `config/volumes.php` file containing references to these variables:
Then create a `config/volumes.php` file that overrides your volume’s `bucket` and `region` settings to the values provided by these environment variables:

```php
<?php

return [
'myS3VolumeHandle' => [
'hasUrls' => true,
'url' => 'https://'.getenv('S3_BUCKET').'.s3.amazonaws.com/',
'keyId' => getenv('S3_API_KEY'),
'secret' => getenv('S3_SECRET'),
'myVolumeHandle' => array_filter([
'bucket' => getenv('S3_BUCKET'),
'region' => getenv('S3_REGION'),
],
]),
];
```

Now any environments that have `S3_BUCKET` and/or `S3_REGION` environment variables defined will override the volume’s `bucket` and `region` settings.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"rss": "https://github.com/craftcms/aws-s3/commits/master.atom"
},
"require": {
"craftcms/cms": "^3.0.0-RC4",
"craftcms/cms": "^3.1.0",
"league/flysystem-aws-s3-v3": "^1.0.13"
},
"autoload": {
Expand Down
25 changes: 19 additions & 6 deletions src/Volume.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ public static function loadBucketList($keyId, $secret)
*/
public function getRootUrl()
{
if (($rootUrl = parent::getRootUrl()) !== false && $this->subfolder) {
$rootUrl .= rtrim($this->subfolder, '/').'/';
if (($rootUrl = parent::getRootUrl()) !== false) {
$rootUrl .= $this->_subfolder();
}
return $rootUrl;
}
Expand Down Expand Up @@ -213,7 +213,7 @@ protected function createAdapter()

$client = static::client($config);

return new AwsS3Adapter($client, $this->bucket, $this->subfolder);
return new AwsS3Adapter($client, $this->bucket, $this->_subfolder());
}

/**
Expand Down Expand Up @@ -261,7 +261,7 @@ protected function invalidateCdnPath(string $path): bool
try {
$cfClient->createInvalidation(
[
'DistributionId' => $this->cfDistributionId,
'DistributionId' => Craft::parseEnv($this->cfDistributionId),
'InvalidationBatch' => [
'Paths' =>
[
Expand All @@ -284,6 +284,19 @@ protected function invalidateCdnPath(string $path): bool
// Private Methods
// =========================================================================

/**
* Returns the parsed subfolder path
* @return string|null
*/
private function _subfolder()
{
if ($this->subfolder && ($subfolder = rtrim(Craft::parseEnv($this->subfolder), '/')) !== '') {
return $subfolder . '/';
}
return null;

}

/**
* Get a CloudFront client.
*
Expand All @@ -301,8 +314,8 @@ private function _getCloudFrontClient()
*/
private function _getConfigArray()
{
$keyId = $this->keyId;
$secret = $this->secret;
$keyId = Craft::parseEnv($this->keyId);
$secret = Craft::parseEnv($this->secret);
$region = $this->region;

return self::_buildConfigArray($keyId, $secret, $region);
Expand Down
4 changes: 2 additions & 2 deletions src/controllers/DefaultController.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public function actionLoadBucketData()
$this->requireAcceptsJson();

$request = Craft::$app->getRequest();
$keyId = $request->getRequiredBodyParam('keyId');
$secret = $request->getRequiredBodyParam('secret');
$keyId = Craft::parseEnv($request->getRequiredBodyParam('keyId'));
$secret = Craft::parseEnv($request->getRequiredBodyParam('secret'));

try {
return $this->asJson(Volume::loadBucketList($keyId, $secret));
Expand Down
12 changes: 8 additions & 4 deletions src/templates/volumeSettings.html
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
{% import "_includes/forms" as forms %}

{{ forms.textField({
{{ forms.autosuggestField({
label: "Access Key ID"|t('aws-s3'),
id: 'keyId',
name: 'keyId',
suggestions: craft.cp.getEnvSuggestions(),
value: volume.keyId,
errors: volume.getErrors('keyId'),
class: 's3-key-id',
instructions: 'You can leave this field empty if you are using an EC2 instance with an applicable IAM role assignment.'|t('aws-s3')
}) }}

{{ forms.textField({
{{ forms.autosuggestField({
label: "Secret Access Key"|t('aws-s3'),
id: 'secret',
name: 'secret',
suggestions: craft.cp.getEnvSuggestions(),
value: volume.secret,
errors: volume.getErrors('secret'),
class: 's3-secret-key',
Expand Down Expand Up @@ -45,12 +47,13 @@
errors: volume.getErrors('bucket'),
}, bucketInput) }}

{{ forms.textField({
{{ forms.autosuggestField({
label: "Subfolder"|t('aws-s3'),
instructions: "If you want to use a bucket’s subfolder as a Volume, specify the path to use here."|t('aws-s3'),
id: 'subfolder',
class: 'ltr',
name: 'subfolder',
suggestions: craft.cp.getEnvSuggestions(),
value: volume.subfolder,
errors: volume.getErrors('subfolder'),
required: false,
Expand Down Expand Up @@ -100,12 +103,13 @@
id: 'cacheDuration',
}, cacheInput) }}

{{ forms.textField({
{{ forms.autosuggestField({
label: "CloudFront Distribution ID"|t('aws-s3'),
instructions: "If you're using CloudFront as CDN for your Assets, enter the distribution ID here so Assets can purge the files from CDN."|t('aws-s3'),
id: 'cfDistributionId',
class: 'ltr',
name: 'cfDistributionId',
suggestions: craft.cp.getEnvSuggestions(),
value: volume.cfDistributionId,
errors: volume.getErrors('cfDistributionId'),
required: false
Expand Down

0 comments on commit c65b134

Please sign in to comment.