Merge pull request #933 from CartoDB/4252-fix-named-map-auth

Forbid access to named map admin resources for everyone but master
This commit is contained in:
Daniel G. Aubert 2018-04-06 15:31:15 +02:00 committed by GitHub
commit a24b7d4c8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 8 deletions

View File

@ -109,7 +109,7 @@ AuthApi.prototype.authorizedByAPIKey = function(user, res, callback) {
return callback(error);
}
return callback(null, true);
return callback(null, true, apikey);
});
};

View File

@ -102,7 +102,7 @@ function authorizedByAPIKey ({ authApi, action, label }) {
return function authorizedByAPIKeyMiddleware (req, res, next) {
const { user } = res.locals;
authApi.authorizedByAPIKey(user, res, (err, authenticated) => {
authApi.authorizedByAPIKey(user, res, (err, authenticated, apikey) => {
if (err) {
return next(err);
}
@ -114,6 +114,15 @@ function authorizedByAPIKey ({ authApi, action, label }) {
return next(error);
}
if (apikey.type !== 'master') {
const error = new Error('Forbidden');
error.type = 'auth';
error.subtype = 'api-key-does-not-grant-access';
error.http_status = 403;
return next(error);
}
next();
});
};

View File

@ -37,7 +37,7 @@ describe('authorization', function() {
});
});
it('should create and get a named map tile using a regular apikey token', function (done) {
it.skip('should create and get a named map tile using a regular apikey token', function (done) {
const apikeyToken = 'regular1';
const mapConfig = {
version: '1.7.0',
@ -61,7 +61,7 @@ describe('authorization', function() {
testClient.drain(done);
});
});
});
it('should fail getting a named map tile with default apikey token', function (done) {
const apikeyTokenCreate = 'regular1';
@ -203,7 +203,7 @@ describe('authorization', function() {
assert.ok(layergroupResult.hasOwnProperty('errors'));
assert.equal(layergroupResult.errors.length, 1);
assert.ok(layergroupResult.errors[0].match(/permission denied/), layergroupResult.errors[0]);
testClient.drain(done);
});
});
@ -257,7 +257,7 @@ describe('authorization', function() {
type: 'source',
params: {
query: 'select * from populated_places_simple_reduced'
}
}
}
]
};
@ -354,7 +354,39 @@ describe('authorization', function() {
});
});
it('should create and get a named map tile using a regular apikey token', function (done) {
it('should fail while listing named maps with a regular apikey token', function (done) {
const apikeyToken = 'regular1';
const testClient = new TestClient({}, apikeyToken);
testClient.getNamedMapList({ response: {status: 403 }}, function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 403);
assert.equal(body.errors.length, 1);
assert.ok(body.errors[0].match(/Forbidden/), body.errors[0]);
testClient.drain(done);
});
});
it('should list named maps with master apikey token', function (done) {
const apikeyToken = 1234;
const testClient = new TestClient({}, apikeyToken);
testClient.getNamedMapList({}, function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert.ok(Array.isArray(body.template_ids));
testClient.drain(done);
});
});
it.skip('should create and get a named map tile using a regular apikey token', function (done) {
const apikeyToken = 'regular1';
const template = {
@ -391,7 +423,7 @@ describe('authorization', function() {
});
});
it('should fail creating a named map using a regular apikey token and a private table', function (done) {
it.skip('should fail creating a named map using a regular apikey token and a private table', function (done) {
const apikeyToken = 'regular1';
const template = {

View File

@ -1254,6 +1254,36 @@ TestClient.prototype.getAnalysesCatalog = function (params, callback) {
);
};
TestClient.prototype.getNamedMapList = function(params, callback) {
const request = {
url: `/api/v1/map/named?${qs.stringify({ api_key: this.apiKey })}`,
method: 'GET',
headers: {
host: 'localhost',
'Content-Type': 'application/json'
}
};
let expectedResponse = {
status: 200,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
};
if (params.response) {
expectedResponse = Object.assign(expectedResponse, params.response);
}
assert.response(this.server, request, expectedResponse, (res, err) => {
if (err) {
return callback(err);
}
const body = JSON.parse(res.body);
return callback(null, res, body);
});
};
TestClient.prototype.getNamedTile = function (name, z, x, y, format, options, callback) {
const { params } = options;