Skip to content

Commit 7932923

Browse files
authored
Validate the configuration path for Google Cloud Storage at start time (PR #73)
1 parent 46ab2d2 commit 7932923

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

src/config.js

+36-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44
// @flow
55

6+
import fs from 'fs';
67
import convict from 'convict';
78
import { getLogger } from './log';
89

910
const log = getLogger('config');
1011

12+
class ConfigurationError extends Error {
13+
name = 'ConfigurationError';
14+
}
15+
1116
function loadConfig() {
1217
const conf = convict({
1318
env: {
@@ -54,7 +59,37 @@ function loadConfig() {
5459

5560
conf.validate();
5661

57-
return conf.getProperties();
62+
const resolvedConfig = conf.getProperties();
63+
64+
validateConfigValues(resolvedConfig);
65+
66+
return resolvedConfig;
67+
}
68+
69+
// This checks if the configured values are valid, and throws otherwise.
70+
function validateConfigValues(config: Config) {
71+
const { googleAuthenticationFilePath } = config;
72+
73+
if (
74+
googleAuthenticationFilePath &&
75+
googleAuthenticationFilePath !== 'MOCKED'
76+
) {
77+
// If some other value is set, we check it ahead of time so that the lib
78+
// doesn't output an error later.
79+
// Note that an empty string is a valid value: in that case the lib will try
80+
// to find the authentication information from other means.
81+
try {
82+
fs.accessSync(googleAuthenticationFilePath, fs.constants.R_OK);
83+
} catch (e) {
84+
log.critical(
85+
'gcs_configuration_error',
86+
`The authentication file '${googleAuthenticationFilePath}' is missing or not readable.`
87+
);
88+
throw new ConfigurationError(
89+
`The authentication file is missing or not readable.`
90+
);
91+
}
92+
}
5893
}
5994

6095
type Config = {|

test/unit/config.test.js

+32
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44
// @flow
5+
6+
import fs from 'fs';
57
import { config, loadConfigForTestsOnly as loadConfig } from '../../src/config';
68

79
describe('config.js', () => {
@@ -35,4 +37,34 @@ describe('config.js', () => {
3537
expect(() => loadConfig()).toThrow();
3638
process.env.NODE_ENV = 'test';
3739
});
40+
41+
it('accepts mocked google authentication paths', () => {
42+
process.env.GCS_AUTHENTICATION_PATH = 'MOCKED';
43+
expect(loadConfig().googleAuthenticationFilePath).toEqual('MOCKED');
44+
delete process.env.GCS_AUTHENTICATION_PATH;
45+
});
46+
47+
it('accepts valid google authentication paths', () => {
48+
const filePath = '/path/to/file';
49+
jest.spyOn(fs, 'accessSync').mockReturnValue();
50+
process.env.GCS_AUTHENTICATION_PATH = filePath;
51+
expect(loadConfig().googleAuthenticationFilePath).toEqual(filePath);
52+
delete process.env.GCS_AUTHENTICATION_PATH;
53+
});
54+
55+
it('rejects google authentication paths that are not readable', () => {
56+
const filePath = '/path/to/file';
57+
jest.spyOn(process.stdout, 'write').mockImplementation(() => {});
58+
jest.spyOn(fs, 'accessSync').mockImplementation(() => {
59+
throw new Error();
60+
});
61+
process.env.GCS_AUTHENTICATION_PATH = filePath;
62+
expect(() => loadConfig()).toThrow(
63+
'The authentication file is missing or not readable.'
64+
);
65+
expect(process.stdout.write).toHaveBeenCalledWith(
66+
expect.stringContaining('CRITICAL')
67+
);
68+
delete process.env.GCS_AUTHENTICATION_PATH;
69+
});
3870
});

0 commit comments

Comments
 (0)