Skip to content

Commit

Permalink
fix: Deny request if master key is not set in Parse Server option `ma…
Browse files Browse the repository at this point in the history
…sterKeyIps` regardless of ACL and CLP (#8957)

BREAKING CHANGE: A request using the master key will now be rejected as unauthorized if the IP from which the request originates is not set in the Parse Server option `masterKeyIps`, even if the request does not require the master key permission, for example for a public object in a public class class.
  • Loading branch information
EhsanParsania authored Mar 1, 2024
1 parent 5452c8f commit a7b5b38
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 16 deletions.
42 changes: 26 additions & 16 deletions spec/Middlewares.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ describe('middlewares', () => {
});

it('should use _ContentType if provided', done => {
AppCachePut(fakeReq.body._ApplicationId, {
masterKeyIps: ['127.0.0.1'],
});
expect(fakeReq.headers['content-type']).toEqual(undefined);
const contentType = 'image/jpeg';
fakeReq.body._ContentType = contentType;
Expand Down Expand Up @@ -153,25 +156,23 @@ describe('middlewares', () => {
});
fakeReq.ip = '127.0.0.1';
fakeReq.headers['x-parse-master-key'] = 'masterKey';
await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve));
expect(fakeReq.auth.isMaster).toBe(false);

let error;

try {
await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve));
} catch (err) {
error = err;
}

expect(error).toBeDefined();
expect(error.message).toEqual(`unauthorized`);
expect(logger.error).toHaveBeenCalledWith(
`Request using master key rejected as the request IP address '127.0.0.1' is not set in Parse Server option 'masterKeyIps'.`
);
});

it('should not succeed if the ip does not belong to masterKeyIps list', async () => {
AppCachePut(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
masterKeyIps: ['10.0.0.1'],
});
fakeReq.ip = '127.0.0.1';
fakeReq.headers['x-parse-master-key'] = 'masterKey';
await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve));
expect(fakeReq.auth.isMaster).toBe(false);
});

it('should not succeed if the ip does not belong to maintenanceKeyIps list', async () => {
it('should not succeed and log if the ip does not belong to maintenanceKeyIps list', async () => {
const logger = require('../lib/logger').logger;
spyOn(logger, 'error').and.callFake(() => {});
AppCachePut(fakeReq.body._ApplicationId, {
Expand All @@ -180,8 +181,17 @@ describe('middlewares', () => {
});
fakeReq.ip = '10.0.0.2';
fakeReq.headers['x-parse-maintenance-key'] = 'masterKey';
await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve));
expect(fakeReq.auth.isMaintenance).toBe(false);

let error;

try {
await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve));
} catch (err) {
error = err;
}

expect(error).toBeDefined();
expect(error.message).toEqual(`unauthorized`);
expect(logger.error).toHaveBeenCalledWith(
`Request using maintenance key rejected as the request IP address '10.0.0.2' is not set in Parse Server option 'maintenanceKeyIps'.`
);
Expand Down
4 changes: 4 additions & 0 deletions src/middlewares.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@ export function handleParseHeaders(req, res, next) {
`Request using master key rejected as the request IP address '${clientIp}' is not set in Parse Server option 'masterKeyIps'.`
);
isMaster = false;
const error = new Error();
error.status = 403;
error.message = `unauthorized`;
throw error;
}

if (isMaster) {
Expand Down

0 comments on commit a7b5b38

Please sign in to comment.