mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
Make it possible to disable CSRF check for the specified list of paths. (#13904)
This commit is contained in:
parent
215d9a066a
commit
ac63d371b5
4 changed files with 71 additions and 1 deletions
|
@ -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');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -79,6 +79,9 @@ export default () => Joi.object({
|
||||||
}),
|
}),
|
||||||
xsrf: Joi.object({
|
xsrf: Joi.object({
|
||||||
disableProtection: Joi.boolean().default(false),
|
disableProtection: Joi.boolean().default(false),
|
||||||
|
whitelist: Joi.array().items(
|
||||||
|
Joi.string().regex(/^\//, 'start with a slash')
|
||||||
|
).default([]),
|
||||||
token: Joi.string().optional().notes('Deprecated')
|
token: Joi.string().optional().notes('Deprecated')
|
||||||
}).default(),
|
}).default(),
|
||||||
}).default(),
|
}).default(),
|
||||||
|
|
|
@ -9,6 +9,7 @@ const src = resolve.bind(null, __dirname, '../../../../src');
|
||||||
const xsrfHeader = 'kbn-xsrf';
|
const xsrfHeader = 'kbn-xsrf';
|
||||||
const versionHeader = 'kbn-version';
|
const versionHeader = 'kbn-version';
|
||||||
const testPath = '/xsrf/test/route';
|
const testPath = '/xsrf/test/route';
|
||||||
|
const whitelistedTestPath = '/xsrf/test/route/whitelisted';
|
||||||
const actualVersion = require(src('../package.json')).version;
|
const actualVersion = require(src('../package.json')).version;
|
||||||
|
|
||||||
describe('xsrf request filter', function () {
|
describe('xsrf request filter', function () {
|
||||||
|
@ -23,7 +24,10 @@ describe('xsrf request filter', function () {
|
||||||
const makeServer = async function () {
|
const makeServer = async function () {
|
||||||
const kbnServer = kbnTestServer.createServer({
|
const kbnServer = kbnTestServer.createServer({
|
||||||
server: {
|
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;
|
return kbnServer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -152,6 +170,16 @@ describe('xsrf request filter', function () {
|
||||||
expect(resp.statusCode).to.be(400);
|
expect(resp.statusCode).to.be(400);
|
||||||
expect(resp.result.message).to.be('Request must contain a kbn-xsrf header.');
|
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');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { badRequest } from 'boom';
|
||||||
|
|
||||||
export default function (kbnServer, server, config) {
|
export default function (kbnServer, server, config) {
|
||||||
const disabled = config.get('server.xsrf.disableProtection');
|
const disabled = config.get('server.xsrf.disableProtection');
|
||||||
|
const whitelist = config.get('server.xsrf.whitelist');
|
||||||
const versionHeader = 'kbn-version';
|
const versionHeader = 'kbn-version';
|
||||||
const xsrfHeader = 'kbn-xsrf';
|
const xsrfHeader = 'kbn-xsrf';
|
||||||
|
|
||||||
|
@ -10,6 +11,10 @@ export default function (kbnServer, server, config) {
|
||||||
return reply.continue();
|
return reply.continue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (whitelist.includes(req.path)) {
|
||||||
|
return reply.continue();
|
||||||
|
}
|
||||||
|
|
||||||
const isSafeMethod = req.method === 'get' || req.method === 'head';
|
const isSafeMethod = req.method === 'get' || req.method === 'head';
|
||||||
const hasVersionHeader = versionHeader in req.headers;
|
const hasVersionHeader = versionHeader in req.headers;
|
||||||
const hasXsrfHeader = xsrfHeader in req.headers;
|
const hasXsrfHeader = xsrfHeader in req.headers;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue