[6.2] Make it possible to disable CSRF check for the specified list of paths. (#16365)

This commit is contained in:
Aleh Zasypkin 2018-01-29 22:27:11 +01:00 committed by GitHub
parent 4884b215b3
commit 5610d54c93
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 1 deletions

View file

@ -164,5 +164,39 @@ describe('Config schema', function () {
});
});
describe('xsrf', () => {
it('disableProtection is `false` by default.', () => {
const { error, value: { server: { xsrf: { disableProtection } } } } = validate({});
expect(error).to.be(null);
expect(disableProtection).to.be(false);
});
it('whitelist is empty by default.', () => {
const { value: { server: { xsrf: { whitelist } } } } = validate({});
expect(whitelist).to.be.an(Array);
expect(whitelist).to.have.length(0);
});
it('whitelist rejects paths that do not start with a slash.', () => {
const config = {};
set(config, 'server.xsrf.whitelist', ['path/to']);
const { error } = validate(config);
expect(error).to.be.an(Object);
expect(error).to.have.property('details');
expect(error.details[0]).to.have.property('path', 'server.xsrf.whitelist.0');
});
it('whitelist accepts paths that start with a slash.', () => {
const config = {};
set(config, 'server.xsrf.whitelist', ['/path/to']);
const { error, value: { server: { xsrf: { whitelist } } } } = validate(config);
expect(error).to.be(null);
expect(whitelist).to.be.an(Array);
expect(whitelist).to.have.length(1);
expect(whitelist).to.contain('/path/to');
});
});
});
});

View file

@ -79,6 +79,9 @@ export default () => Joi.object({
}),
xsrf: Joi.object({
disableProtection: Joi.boolean().default(false),
whitelist: Joi.array().items(
Joi.string().regex(/^\//, 'start with a slash')
).default([]),
token: Joi.string().optional().notes('Deprecated')
}).default(),
}).default(),

View file

@ -9,6 +9,7 @@ const src = resolve.bind(null, __dirname, '../../../../src');
const xsrfHeader = 'kbn-xsrf';
const versionHeader = 'kbn-version';
const testPath = '/xsrf/test/route';
const whitelistedTestPath = '/xsrf/test/route/whitelisted';
const actualVersion = require(src('../package.json')).version;
describe('xsrf request filter', function () {
@ -23,7 +24,10 @@ describe('xsrf request filter', function () {
const makeServer = async function () {
const kbnServer = kbnTestServer.createServer({
server: {
xsrf: { disableProtection: false }
xsrf: {
disableProtection: false,
whitelist: [whitelistedTestPath]
}
}
});
@ -51,6 +55,20 @@ describe('xsrf request filter', function () {
}
});
kbnServer.server.route({
path: whitelistedTestPath,
method: destructiveMethods,
config: {
// Disable payload parsing to make HapiJS server accept any content-type header.
payload: {
parse: false
}
},
handler: function (req, reply) {
reply(null, 'ok');
}
});
return kbnServer;
};
@ -152,6 +170,16 @@ describe('xsrf request filter', function () {
expect(resp.statusCode).to.be(400);
expect(resp.result.message).to.be('Request must contain a kbn-xsrf header.');
});
it('accepts whitelisted requests without either an xsrf or version header', async function () {
const resp = await inject(kbnServer, {
url: whitelistedTestPath,
method: method
});
expect(resp.statusCode).to.be(200);
expect(resp.payload).to.be('ok');
});
});
}
});

View file

@ -2,6 +2,7 @@ import { badRequest } from 'boom';
export default function (kbnServer, server, config) {
const disabled = config.get('server.xsrf.disableProtection');
const whitelist = config.get('server.xsrf.whitelist');
const versionHeader = 'kbn-version';
const xsrfHeader = 'kbn-xsrf';
@ -10,6 +11,10 @@ export default function (kbnServer, server, config) {
return reply.continue();
}
if (whitelist.includes(req.path)) {
return reply.continue();
}
const isSafeMethod = req.method === 'get' || req.method === 'head';
const hasVersionHeader = versionHeader in req.headers;
const hasXsrfHeader = xsrfHeader in req.headers;