Don't start in production if important security fields are misconfigured
This commit is contained in:
parent
7a96790f97
commit
9ce345d99d
@ -8,7 +8,7 @@ export default {
|
|||||||
public_url: "http://localhost:4899",
|
public_url: "http://localhost:4899",
|
||||||
public_websocket_url: "ws://localhost:4899",
|
public_websocket_url: "ws://localhost:4899",
|
||||||
port: 4899,
|
port: 4899,
|
||||||
gitlab_webhook_token: 'secret',
|
gitlab_webhook_token: 'default',
|
||||||
mysql: {
|
mysql: {
|
||||||
connectionLimit: 10,
|
connectionLimit: 10,
|
||||||
host: "localhost",
|
host: "localhost",
|
||||||
@ -23,7 +23,7 @@ export default {
|
|||||||
prefix: 'wms'
|
prefix: 'wms'
|
||||||
},
|
},
|
||||||
session: {
|
session: {
|
||||||
secret: "very_secret_not_known",
|
secret: 'default',
|
||||||
cookie: {
|
cookie: {
|
||||||
secure: false,
|
secure: false,
|
||||||
maxAge: 30 * 24 * 3600 * 1000, // 30 days
|
maxAge: 30 * 24 * 3600 * 1000, // 30 days
|
||||||
|
@ -62,6 +62,11 @@ export default abstract class Application {
|
|||||||
// Register all components and alike
|
// Register all components and alike
|
||||||
await this.init();
|
await this.init();
|
||||||
|
|
||||||
|
// Security
|
||||||
|
if (process.env.NODE_ENV === 'production') {
|
||||||
|
await this.checkSecuritySettings();
|
||||||
|
}
|
||||||
|
|
||||||
// Init express
|
// Init express
|
||||||
const app = express();
|
const app = express();
|
||||||
const initRouter = express.Router();
|
const initRouter = express.Router();
|
||||||
@ -171,6 +176,12 @@ export default abstract class Application {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async checkSecuritySettings(): Promise<void> {
|
||||||
|
for (const component of this.components) {
|
||||||
|
await component.checkSecuritySettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async stop(): Promise<void> {
|
async stop(): Promise<void> {
|
||||||
Logger.info('Stopping application...');
|
Logger.info('Stopping application...');
|
||||||
|
|
||||||
|
@ -2,11 +2,16 @@ import {Express, Router} from "express";
|
|||||||
import Logger from "./Logger";
|
import Logger from "./Logger";
|
||||||
import {sleep} from "./Utils";
|
import {sleep} from "./Utils";
|
||||||
import Application from "./Application";
|
import Application from "./Application";
|
||||||
|
import config from "config";
|
||||||
|
import SecurityError from "./SecurityError";
|
||||||
|
|
||||||
export default abstract class ApplicationComponent<T> {
|
export default abstract class ApplicationComponent<T> {
|
||||||
private val?: T;
|
private val?: T;
|
||||||
protected app?: Application;
|
protected app?: Application;
|
||||||
|
|
||||||
|
public async checkSecuritySettings(): Promise<void> {
|
||||||
|
}
|
||||||
|
|
||||||
public async start(app: Express): Promise<void> {
|
public async start(app: Express): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,4 +65,10 @@ export default abstract class ApplicationComponent<T> {
|
|||||||
Logger.error(e, `An error occurred while closing the ${thingName}.`);
|
Logger.error(e, `An error occurred while closing the ${thingName}.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected checkSecurityConfigField(field: string) {
|
||||||
|
if (!config.has(field) || config.get<string>(field) === 'default') {
|
||||||
|
throw new SecurityError('field not configured.');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
8
src/SecurityError.ts
Normal file
8
src/SecurityError.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export default class SecurityError implements Error {
|
||||||
|
public readonly name: string = 'SecurityError';
|
||||||
|
public readonly message: string;
|
||||||
|
|
||||||
|
public constructor(message: string) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,10 @@ import {ForbiddenHttpError} from "../HttpError";
|
|||||||
import Logger from "../Logger";
|
import Logger from "../Logger";
|
||||||
|
|
||||||
export default class AutoUpdateComponent extends ApplicationComponent<void> {
|
export default class AutoUpdateComponent extends ApplicationComponent<void> {
|
||||||
|
public async checkSecuritySettings(): Promise<void> {
|
||||||
|
this.checkSecurityConfigField('gitlab_webhook_token');
|
||||||
|
}
|
||||||
|
|
||||||
public async init(router: Router): Promise<void> {
|
public async init(router: Router): Promise<void> {
|
||||||
router.post('/update/push.json', (req, res) => {
|
router.post('/update/push.json', (req, res) => {
|
||||||
const token = req.header('X-Gitlab-Token');
|
const token = req.header('X-Gitlab-Token');
|
||||||
|
@ -1,8 +1,21 @@
|
|||||||
import ApplicationComponent from "../ApplicationComponent";
|
import ApplicationComponent from "../ApplicationComponent";
|
||||||
import {Express} from "express";
|
import {Express} from "express";
|
||||||
import Mail from "../Mail";
|
import Mail from "../Mail";
|
||||||
|
import config from "config";
|
||||||
|
import SecurityError from "../SecurityError";
|
||||||
|
|
||||||
export default class MailComponent extends ApplicationComponent<void> {
|
export default class MailComponent extends ApplicationComponent<void> {
|
||||||
|
|
||||||
|
|
||||||
|
public async checkSecuritySettings(): Promise<void> {
|
||||||
|
if (!config.get<boolean>('mail.secure')) {
|
||||||
|
throw new SecurityError('Cannot set mail.secure to false');
|
||||||
|
}
|
||||||
|
if (config.get<boolean>('mail.allow_invalid_tls')) {
|
||||||
|
throw new SecurityError('Cannot set mail.allow_invalid_tls to true');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async start(app: Express): Promise<void> {
|
public async start(app: Express): Promise<void> {
|
||||||
await this.prepare('Mail connection', () => Mail.prepare());
|
await this.prepare('Mail connection', () => Mail.prepare());
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import config from "config";
|
|||||||
import RedisComponent from "./RedisComponent";
|
import RedisComponent from "./RedisComponent";
|
||||||
import flash from "connect-flash";
|
import flash from "connect-flash";
|
||||||
import {Router} from "express";
|
import {Router} from "express";
|
||||||
|
import SecurityError from "../SecurityError";
|
||||||
|
|
||||||
export default class SessionComponent extends ApplicationComponent<void> {
|
export default class SessionComponent extends ApplicationComponent<void> {
|
||||||
private readonly storeComponent: RedisComponent;
|
private readonly storeComponent: RedisComponent;
|
||||||
@ -13,6 +14,14 @@ export default class SessionComponent extends ApplicationComponent<void> {
|
|||||||
this.storeComponent = storeComponent;
|
this.storeComponent = storeComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async checkSecuritySettings(): Promise<void> {
|
||||||
|
this.checkSecurityConfigField('session.secret');
|
||||||
|
if (!config.get<boolean>('session.cookie.secure')) {
|
||||||
|
throw new SecurityError('Cannot set cookie secure field to false.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async init(router: Router): Promise<void> {
|
public async init(router: Router): Promise<void> {
|
||||||
router.use(session({
|
router.use(session({
|
||||||
saveUninitialized: true,
|
saveUninitialized: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user