Skip to content

Commit

Permalink
Update /os/v1/config endpoint for config.json migration
Browse files Browse the repository at this point in the history
  • Loading branch information
cywang117 committed Sep 13, 2023
1 parent d8707b7 commit bcfb43d
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 15 deletions.
48 changes: 33 additions & 15 deletions src/features/os-config/index.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,45 @@
import type { Application, RequestHandler } from 'express';
import type { Application } from 'express';

import {
DEVICE_CONFIG_OPENVPN_CA,
DEVICE_CONFIG_OPENVPN_CONFIG,
DEVICE_CONFIG_SSH_AUTHORIZED_KEYS,
LOGS_HOST,
} from '../../lib/config';
import { b64decode } from '../../lib/utils';

const getOsConfiguration: RequestHandler = (_req, res) => {
res.json({
services: {
openvpn: {
config: DEVICE_CONFIG_OPENVPN_CONFIG,
ca: b64decode(DEVICE_CONFIG_OPENVPN_CA),
},
ssh: {
authorized_keys: DEVICE_CONFIG_SSH_AUTHORIZED_KEYS,
},
},
schema_version: '1.0.0',
});
// OS service configurations
const services = {
openvpn: {
config: DEVICE_CONFIG_OPENVPN_CONFIG,
ca: b64decode(DEVICE_CONFIG_OPENVPN_CA),
},
ssh: {
authorized_keys: DEVICE_CONFIG_SSH_AUTHORIZED_KEYS,
},
};

// Config.json migrations: Changes should be evaluated for security risks before applying.
//
// - A field may not be deleted from config.json.
// - A field with a value of non-null tells os-config that the value will be updated
// to the new value if it's different.
// - A field not found in the whitelist of the os-config schema will be ignored.
const config = {
overrides: {
...(LOGS_HOST != null && { logsEndpoint: `https://${LOGS_HOST}` }),
},
};

export const setup = (app: Application) => {
app.get('/os/v1/config/', getOsConfiguration);
app.get('/os/v1/config/', (_req, res) => {
res.json({
services,
// Older os-configs don't know how to handle the config field, but
// luckily serde-rs ignores unknown fields by default.
config,
/** @deprecated schema_version is an outdated field kept for compatibility with legacy os-configs */
schema_version: '1.0.0',
});
});
};
35 changes: 35 additions & 0 deletions test/22_os-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { expect } from 'chai';

import { supertest } from './test-lib/supertest';
import { LOGS_HOST } from '../src/lib/config';

describe('OS configuration endpoints', () => {
describe('/os/v1/config', () => {
it('should return a valid JSON response', async () => {
const { body } = await supertest().get('/os/v1/config').expect(200);

// Service configurations should be valid for their respective services
expect(body)
.to.have.property('services')
.that.has.all.keys('openvpn', 'ssh');
expect(body.services.openvpn).to.have.all.keys('config', 'ca');
expect(body.services.openvpn.config).to.be.a('string');
expect(body.services.openvpn.ca).to.be.a('string');
expect(body.services.ssh)
.to.have.property('authorized_keys')
.that.is.a('string');

// schema_version is kept for backwards compatibility
expect(body).to.have.property('schema_version').that.equals('1.0.0');

// Config should contain config.json overrides
expect(body)
.to.have.property('config')
.that.deep.equals({
overrides: {
...(LOGS_HOST != null && { logsEndpoint: `https://${LOGS_HOST}` }),
},
});
});
});
});

0 comments on commit bcfb43d

Please sign in to comment.