Переглянути джерело

companion: Secrets From File

Make reading secrets from files specified in "..._SECRET_FILE" environment variables possible to support Docker secrets.
Jonas Thelemann 5 роки тому
батько
коміт
a8e17bee5f

+ 5 - 0
packages/@uppy/companion/env_example

@@ -6,18 +6,23 @@ COMPANION_SELF_ENDPOINT=uppy.xxxx.com
 COMPANION_PROTOCOL=https
 COMPANION_DATADIR=/mnt/uppy-server-data
 COMPANION_SECRET=
+COMPANION_SECRET_FILE=
 
 COMPANION_DROPBOX_KEY="dropbox_key"
 COMPANION_DROPBOX_SECRET="dropbox_secret"
+COMPANION_DROPBOX_SECRET_FILE="path/to/dropbox/secret"
 
 COMPANION_GOOGLE_KEY=
 COMPANION_GOOGLE_SECRET=
+COMPANION_GOOGLE_SECRET_FILE=
 
 COMPANION_INSTAGRAM_KEY=
 COMPANION_INSTAGRAM_SECRET=
+COMPANION_INSTAGRAM_SECRET_FILE=
 
 COMPANION_AWS_KEY=
 COMPANION_AWS_SECRET=
+COMPANION_AWS_SECRET_FILE=
 COMPANION_AWS_BUCKET=
 COMPANION_AWS_ENDPOINT=
 COMPANION_AWS_REGION=

+ 8 - 1
packages/@uppy/companion/src/server/provider/index.js

@@ -5,6 +5,7 @@
 const config = require('@purest/providers')
 const dropbox = require('./dropbox')
 const drive = require('./drive')
+const fs = require('fs')
 const instagram = require('./instagram')
 const { getURLBuilder } = require('../helpers/utils')
 const logger = require('../logger')
@@ -132,7 +133,13 @@ module.exports.addProviderOptions = (options, grantConfig) => {
     if (grantConfig[authProvider]) {
       // explicitly add providerOptions so users don't override other providerOptions.
       grantConfig[authProvider].key = providerOptions[authProvider].key
-      grantConfig[authProvider].secret = providerOptions[authProvider].secret
+
+      // only read and override a secret from file if such a file is not undefined
+      if (typeof providerOptions[authProvider].secretFile === 'string') {
+        grantConfig[authProvider].secret = fs.readFileSync(providerOptions[authProvider].secretFile).toString()
+      } else {
+        grantConfig[authProvider].secret = providerOptions[authProvider].secret
+      }
 
       // override grant.js redirect uri with uppy's custom redirect url
       if (oauthDomain) {

+ 5 - 5
packages/@uppy/companion/src/standalone/helper.js

@@ -32,19 +32,19 @@ const getConfigFromEnv = () => {
     providerOptions: {
       google: {
         key: process.env.COMPANION_GOOGLE_KEY,
-        secret: process.env.COMPANION_GOOGLE_SECRET
+        secret: typeof process.env.COMPANION_GOOGLE_SECRET_FILE === 'string' ? fs.readFileSync(process.env.COMPANION_GOOGLE_SECRET_FILE).toString() : process.env.COMPANION_GOOGLE_SECRET
       },
       dropbox: {
         key: process.env.COMPANION_DROPBOX_KEY,
-        secret: process.env.COMPANION_DROPBOX_SECRET
+        secret: typeof process.env.COMPANION_DROPBOX_SECRET_FILE === 'string' ? fs.readFileSync(process.env.COMPANION_DROPBOX_SECRET_FILE).toString() : process.env.COMPANION_DROPBOX_SECRET
       },
       instagram: {
         key: process.env.COMPANION_INSTAGRAM_KEY,
-        secret: process.env.COMPANION_INSTAGRAM_SECRET
+        secret: typeof process.env.COMPANION_INSTAGRAM_SECRET_FILE === 'string' ? fs.readFileSync(process.env.COMPANION_INSTAGRAM_SECRET_FILE).toString() : process.env.COMPANION_INSTAGRAM_SECRET
       },
       s3: {
         key: process.env.COMPANION_AWS_KEY,
-        secret: process.env.COMPANION_AWS_SECRET,
+        secret: typeof process.env.COMPANION_AWS_SECRET_FILE === 'string' ? fs.readFileSync(process.env.COMPANION_AWS_SECRET_FILE).toString() : process.env.COMPANION_AWS_SECRET,
         bucket: process.env.COMPANION_AWS_BUCKET,
         endpoint: process.env.COMPANION_AWS_ENDPOINT,
         region: process.env.COMPANION_AWS_REGION
@@ -62,7 +62,7 @@ const getConfigFromEnv = () => {
     redisUrl: process.env.COMPANION_REDIS_URL,
     sendSelfEndpoint: process.env.COMPANION_SELF_ENDPOINT,
     uploadUrls: uploadUrls ? uploadUrls.split(',') : null,
-    secret: process.env.COMPANION_SECRET || generateSecret(),
+    secret: typeof process.env.COMPANION_SECRET_FILE === 'string' ? fs.readFileSync(process.env.COMPANION_SECRET_FILE).toString() : process.env.COMPANION_SECRET || generateSecret(),
     debug: process.env.NODE_ENV !== 'production',
     // TODO: this is a temporary hack to support distributed systems.
     // it is not documented, because it should be changed soon.

+ 14 - 0
packages/@uppy/companion/test/__tests__/provider-manager.js

@@ -22,6 +22,20 @@ describe('Test Provider options', () => {
     expect(grantConfig.instagram.secret).toBe('instagram_secret')
   })
 
+  test('adds provider options for secret files', () => {
+    process.env.COMPANION_DROPBOX_SECRET_FILE = process.env.PWD + '/test/resources/dropbox_secret_file'
+    process.env.COMPANION_GOOGLE_SECRET_FILE = process.env.PWD + '/test/resources/google_secret_file'
+    process.env.COMPANION_INSTAGRAM_SECRET_FILE = process.env.PWD + '/test/resources/instagram_secret_file'
+
+    uppyOptions = require('../../src/standalone/helper').getUppyOptions()
+
+    providerManager.addProviderOptions(uppyOptions, grantConfig)
+
+    expect(grantConfig.dropbox.secret).toBe('xobpord')
+    expect(grantConfig.google.secret).toBe('elgoog')
+    expect(grantConfig.instagram.secret).toBe('margatsni')
+  })
+
   test('does not add provider options if protocol and host are not set', () => {
     delete uppyOptions.server.host
     delete uppyOptions.server.protocol

+ 1 - 0
packages/@uppy/companion/test/resources/dropbox_secret_file

@@ -0,0 +1 @@
+xobpord

+ 1 - 0
packages/@uppy/companion/test/resources/google_secret_file

@@ -0,0 +1 @@
+elgoog

+ 1 - 0
packages/@uppy/companion/test/resources/instagram_secret_file

@@ -0,0 +1 @@
+margatsni

+ 8 - 1
website/src/docs/companion.md

@@ -121,6 +121,7 @@ To run Companion as a standalone server, you are required to set your Uppy [Opti
 
 # any long set of random characters for the server session
 export COMPANION_SECRET="shh!Issa Secret!"
+export COMPANION_SECRET_FILE="PATH/TO/COMPANION/SECRET/FILE"
 # corresponds to the server.host option
 export COMPANION_DOMAIN="YOUR SERVER DOMAIN"
 # corresponds to the filePath option
@@ -151,18 +152,22 @@ export COMPANION_REDIS_URL="REDIS URL"
 # to enable Dropbox
 export COMPANION_DROPBOX_KEY="YOUR DROPBOX KEY"
 export COMPANION_DROPBOX_SECRET="YOUR DROPBOX SECRET"
+export COMPANION_DROPBOX_SECRET_FILE="PATH/TO/DROPBOX/SECRET/FILE"
 
 # to enable Google Drive
 export COMPANION_GOOGLE_KEY="YOUR GOOGLE KEY"
 export COMPANION_GOOGLE_SECRET="YOUR GOOGLE SECRET"
+export COMPANION_GOOGLE_SECRET_FILE="PATH/TO/GOOGLE/SECRET/FILE"
 
 # to enable Instagram
 export COMPANION_INSTAGRAM_KEY="YOUR INSTAGRAM KEY"
 export COMPANION_INSTAGRAM_SECRET="YOUR INSTAGRAM SECRET"
+export COMPANION_INSTAGRAM_SECRET_FILE="PATH/TO/INSTAGRAM/SECRET/FILE"
 
 # to enable S3
 export COMPANION_AWS_KEY="YOUR AWS KEY"
 export COMPANION_AWS_SECRET="YOUR AWS SECRET"
+export COMPANION_AWS_SECRET_FILE="PATH/TO/AWS/SECRET/FILE"
 export COMPANION_AWS_BUCKET="YOUR AWS S3 BUCKET"
 export COMPANION_AWS_REGION="AWS REGION"
 
@@ -181,6 +186,8 @@ export COMPANION_UPLOAD_URLS="http://master.tus.io/files/,https://master.tus.io/
 
 See [env.example.sh](https://github.com/transloadit/uppy/blob/master/env.example.sh) for an example configuration script.
 
+If a `...SECRET_FILE"` environment variable is defined, the according `secret` will be overridden by the file's content.
+
 ### Options
 
 ```javascript
@@ -279,7 +286,7 @@ let options = {
                 access_url: "https://mywebsite.com/token",
                 oauth: 2,
                 key: "***",
-                secret: "**",
+                secret: "***",
                 scope: ["read", "write"]
             },
             module: require('/path/to/provider/module')