Skip to content

Commit f28b9b2

Browse files
committed
add support for passing API_SECRET to a container via a file
1 parent 9cd304f commit f28b9b2

File tree

3 files changed

+83
-9
lines changed

3 files changed

+83
-9
lines changed

lib/server/enclave.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const init = function init () {
4444
}
4545

4646
enclave.isApiKeySet = function isApiKeySet () {
47-
return isApiKeySet;
47+
return apiKeySet;
4848
}
4949

5050
enclave.isApiKey = function isApiKey (keyValue) {

lib/server/env.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,19 @@ function setSSL () {
7777
env.secureCspReportOnly = readENVTruthy("SECURE_CSP_REPORT_ONLY", false);
7878
}
7979

80-
// A little ugly, but we don't want to read the secret into a var
8180
function setAPISecret () {
82-
var useSecret = (readENV('API_SECRET') && readENV('API_SECRET').length > 0);
81+
// if no value is provided as an environment variable, try to read it from a file
82+
const apiSecret = readENV('API_SECRET') || readEnvFile('API_SECRET_FILE');
8383
//TODO: should we clear API_SECRET from process env?
8484
env.api_secret = null;
8585
// if a passphrase was provided, get the hex digest to mint a single token
86-
if (useSecret) {
87-
if (readENV('API_SECRET').length < consts.MIN_PASSPHRASE_LENGTH) {
86+
if (apiSecret && apiSecret.length > 0) {
87+
if (apiSecret.length < consts.MIN_PASSPHRASE_LENGTH) {
8888
var msg = ['API_SECRET should be at least', consts.MIN_PASSPHRASE_LENGTH, 'characters'].join(' ');
8989
console.error(msg);
9090
env.err.push({ desc: msg });
9191
} else {
92-
93-
const apiSecret = readENV('API_SECRET');
9492
delete process.env.API_SECRET;
95-
9693
env.enclave.setApiKey(apiSecret);
9794
var testresult = stringEntropy(apiSecret);
9895

@@ -108,7 +105,6 @@ function setAPISecret () {
108105
env.notifies.push({ persistent: true, title: 'Security issue', message: 'MongoDB password and API_SECRET match. This is a really bad idea. Please change both and do not reuse passwords across the system.' });
109106
}
110107
}
111-
112108
}
113109
}
114110
}
@@ -185,6 +181,21 @@ function readENVTruthy (varName, defaultValue) {
185181
return value;
186182
}
187183

184+
function readEnvFile(varName) {
185+
let value = null;
186+
const fileName = readENV(varName);
187+
188+
if (fileName && fileName.length > 0) {
189+
try {
190+
value = fs.readFileSync(fileName);
191+
} catch (error) {
192+
env.err.push({ desc: `Unable to read ${varName}: ${error.message}` });
193+
}
194+
}
195+
196+
return value;
197+
}
198+
188199
function findExtendedSettings (envs) {
189200
var extended = {};
190201

tests/env.test.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,71 @@
11
'use strict';
22

33
require('should');
4+
const fs = require('fs');
5+
const os = require('os');
6+
const path = require('path');
47

58
describe('env', function () {
9+
function writeTempFile(fileName, data) {
10+
const fullPath = path.join(os.tmpdir(), fileName);
11+
fs.writeFileSync(fullPath, data);
12+
return fullPath;
13+
}
14+
15+
it('should not set the API key without API_SECRET or API_SECRET_FILE', function () {
16+
delete process.env.API_SECRET;
17+
var env = require( '../lib/server/env' )();
18+
env.enclave.isApiKeySet().should.equal(false);
19+
});
20+
21+
it('should read the API key from API_SECRET_FILE if it is valid', function () {
22+
const apiSecretFile = 'this is another pass phrase';
23+
const hashFile = 'c79c6db1070da3537d0162e60647b0a588769f8d';
24+
process.env.API_SECRET_FILE = writeTempFile('api_secret_file', apiSecretFile);
25+
26+
var env = require( '../lib/server/env' )();
27+
env.enclave.isApiKeySet().should.equal(true);
28+
env.enclave.isApiKey(hashFile).should.equal(true);
29+
30+
fs.rmSync(process.env.API_SECRET_FILE);
31+
delete process.env.API_SECRET_FILE;
32+
});
33+
34+
it('should raise an error when API_SECRET_FILE does not exist', function () {
35+
const nonexistentPath = path.join(os.tmpdir(), 'api_secret_file');
36+
process.env.API_SECRET_FILE = nonexistentPath;
37+
38+
var env = require( '../lib/server/env' )();
39+
env.enclave.isApiKeySet().should.equal(false);
40+
env.err.length.should.equal(1);
41+
42+
const error = env.err.pop();
43+
error.should.have.property('desc');
44+
error.desc.should.match(/API_SECRET_FILE/);
45+
error.desc.should.match(/no such file or directory/);
46+
47+
delete process.env.API_SECRET_FILE;
48+
});
49+
50+
it('should use API_SECRET when API_SECRET_FILE is also specified', function () {
51+
const apiSecretEnv = 'this is my long pass phrase';
52+
const hashEnv = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
53+
process.env.API_SECRET = apiSecretEnv;
54+
55+
const apiSecretFile = 'this is another pass phrase';
56+
const hashFile = 'c79c6db1070da3537d0162e60647b0a588769f8d';
57+
process.env.API_SECRET_FILE = writeTempFile('api_secret_file', apiSecretFile);
58+
59+
var env = require( '../lib/server/env' )();
60+
env.enclave.isApiKeySet().should.equal(true);
61+
env.enclave.isApiKey(hashEnv).should.equal(true);
62+
env.enclave.isApiKey(hashFile).should.equal(false);
63+
64+
fs.rmSync(process.env.API_SECRET_FILE);
65+
delete process.env.API_SECRET_FILE;
66+
delete process.env.API_SECRET;
67+
});
68+
669
it( 'show the right plugins', function () {
770
process.env.SHOW_PLUGINS = 'iob';
871
process.env.ENABLE = 'iob cob';

0 commit comments

Comments
 (0)