Skip to content

Commit

Permalink
companion: allow providing any S3 option, closes #1388 (#2030)
Browse files Browse the repository at this point in the history
* companion: allow providing any S3 option, closes #1388

Now you can configure any S3 option listed in
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property.

It adds a warning about the official S3 names `accessKeyId` and
`secretAccessKey` because you should use the Companion-style names `key`
and `secret` instead.

* companion: use awsClientOptions property for Aws SDK config

* companion: also reject keys inside awsClientOptions

* should keep the checks next to each other

* companion: first check if awsClientOptions isnt null
  • Loading branch information
goto-bus-stop authored Mar 4, 2020
1 parent b2b24a2 commit d191703
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 18 deletions.
35 changes: 23 additions & 12 deletions packages/@uppy/companion/src/companion.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,25 +218,36 @@ const getOptionsMiddleware = (options) => {
if (options.providerOptions.s3) {
const S3 = require('aws-sdk/clients/s3')
const AWS = require('aws-sdk')
const config = options.providerOptions.s3
const s3ProviderOptions = options.providerOptions.s3

if (s3ProviderOptions.accessKeyId || s3ProviderOptions.secretAccessKey) {
throw new Error('Found `providerOptions.s3.accessKeyId` or `providerOptions.s3.secretAccessKey` configuration, but Companion requires `key` and `secret` option names instead. Please use the `key` property instead of `accessKeyId` and the `secret` property instead of `secretAccessKey`.')
}

const rawClientOptions = s3ProviderOptions.awsClientOptions
if (rawClientOptions && (rawClientOptions.accessKeyId || rawClientOptions.secretAccessKey)) {
throw new Error('Found unsupported `providerOptions.s3.awsClientOptions.accessKeyId` or `providerOptions.s3.awsClientOptions.secretAccessKey` configuration. Please use the `providerOptions.s3.key` and `providerOptions.s3.secret` options instead.')
}

const s3ClientOptions = Object.assign({
signatureVersion: 'v4',
// backwards compat
useAccelerateEndpoint: s3ProviderOptions.useAccelerateEndpoint
}, rawClientOptions)

// Use credentials to allow assumed roles to pass STS sessions in.
// If the user doesn't specify key and secret, the default credentials (process-env)
// will be used by S3 in calls below.
let credentials
if (config.key && config.secret) {
credentials = new AWS.Credentials(config.key, config.secret, config.sessionToken)
if (s3ProviderOptions.key && s3ProviderOptions.secret && !s3ClientOptions.credentials) {
s3ClientOptions.credentials = new AWS.Credentials(
s3ProviderOptions.key,
s3ProviderOptions.secret,
s3ProviderOptions.sessionToken)
}
s3Client = new S3({
region: config.region,
endpoint: config.endpoint,
credentials,
signatureVersion: 'v4',
useAccelerateEndpoint: config.useAccelerateEndpoint
})
s3Client = new S3(s3ClientOptions)
}

/**
*
* @param {object} req
* @param {object} res
* @param {function} next
Expand Down
41 changes: 35 additions & 6 deletions website/src/docs/companion.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,37 @@ See [env.example.sh](https://github.com/transloadit/uppy/blob/master/env.example

### S3 options

The S3 uploader has some options in addition to the ones necessary for authentication.
Companion comes with signature endpoints for AWS S3. These can be used by the Uppy client to sign requests to upload files directly to S3, without exposing secret S3 keys in the browser. Companion also supports uploading files from providers like Dropbox and Instagram directly into S3.

The S3 features can be configured using the `providerOptions.s3` property.

#### `providerOptions.s3.key`

The S3 access key ID. The standalone Companion server populates this with the value of the `COMPANION_AWS_KEY` environment variable by default.

#### `providerOptions.s3.secret`

The S3 secret access key. The standalone Companion server populates this with the value of the `COMPANION_AWS_SECRET` environment variable by default.

#### `providerOptions.s3.bucket`

The name of the bucket to store uploaded files in. The standalone Companion server populates this with the value of the `COMPANION_AWS_BUCKET` environment variable by default.

#### `providerOptions.s3.region`

The datacenter region where the target bucket is located. The standalone Companion server populates this with the value of the `COMPANION_AWS_REGION` environment variable by default.

#### `providerOptions.s3.awsClientOptions`

You can supply any [S3 option supported by the AWS SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property) in the `providerOptions.s3.awsClientOptions` object, _except for_ the below:

- `accessKeyId`. Instead, use the `providerOptions.s3.key` property. This is to make configuration names consistent between different Companion features.
- `secretAccessKey`. Instead, use the `providerOptions.s3.secret` property. This is to make configuration names consistent between different Companion features.

Be aware that some options may cause wrong behaviour if they conflict with Companion's assumptions. If you find that a particular option does not work as expected, please [open an issue on the Uppy repository](https://github.com/transloadit/uppy/issues/new) so we can document it here.

#### `providerOptions.s3.getKey(req, filename, metadata)`

#### `s3.getKey(req, filename, metadata)`
a
Get the key name for a file. The key is the file path to which the file will be uploaded in your bucket. This option should be a function receiving three arguments:
- `req`, the HTTP request, for _regular_ S3 uploads using the `@uppy/aws-s3` plugin. This parameter is _not_ available for multipart uploads using the `@uppy/aws-s3-multipart` plugin;
- `filename`, the original name of the uploaded file;
Expand All @@ -308,9 +335,11 @@ This function should return a string `key`. The `req` parameter can be used to u
```js
app.use(authenticationMiddleware)
app.use(uppy.app({
s3: {
getKey: (req, filename, metadata) => `${req.user.id}/${filename}`,
/* auth options */
providerOptions: {
s3: {
getKey: (req, filename, metadata) => `${req.user.id}/${filename}`,
/* auth options */
}
}
}))
```
Expand Down

0 comments on commit d191703

Please sign in to comment.