Compare commits

...

4 Commits

Author SHA1 Message Date
Maha Benzekri c69b8617c5
edit: update arsenal package 2023-10-30 14:43:33 +01:00
Will Toozs e99bb1e1cc
change variable names for clarity 2023-09-15 17:52:03 +02:00
Will Toozs cd6320c432
edit: update arsenal package 2023-09-12 11:14:45 +02:00
Will Toozs 3bc66f8cea
CLDSRV-424: api call updated with implicit deny logic 2023-09-11 18:05:21 +02:00
3 changed files with 49 additions and 9 deletions

View File

@ -107,6 +107,7 @@ const api = {
// no need to check auth on website or cors preflight requests // no need to check auth on website or cors preflight requests
if (apiMethod === 'websiteGet' || apiMethod === 'websiteHead' || if (apiMethod === 'websiteGet' || apiMethod === 'websiteHead' ||
apiMethod === 'corsPreflight') { apiMethod === 'corsPreflight') {
request.actionImplicitDenies = false;
return this[apiMethod](request, log, callback); return this[apiMethod](request, log, callback);
} }
@ -129,15 +130,25 @@ const api = {
const requestContexts = prepareRequestContexts(apiMethod, request, const requestContexts = prepareRequestContexts(apiMethod, request,
sourceBucket, sourceObject, sourceVersionId); sourceBucket, sourceObject, sourceVersionId);
// Extract all the _apiMethods and store them in an array
const apiMethods = requestContexts ? requestContexts.map(context => context._apiMethod) : [];
// Attach the names to the current request
// eslint-disable-next-line no-param-reassign
request.apiMethods = apiMethods;
function checkAuthResults(authResults) { function checkAuthResults(authResults) {
let returnTagCount = true; let returnTagCount = true;
const isImplicitDeny = {};
let isOnlyImplicitDeny = true;
if (apiMethod === 'objectGet') { if (apiMethod === 'objectGet') {
// first item checks s3:GetObject(Version) action // first item checks s3:GetObject(Version) action
if (!authResults[0].isAllowed) { if (!authResults[0].isAllowed && !authResults[0].isImplicit) {
log.trace('get object authorization denial from Vault'); log.trace('get object authorization denial from Vault');
return errors.AccessDenied; return errors.AccessDenied;
} }
// TODO add support for returnTagCount in the bucket policy
// checks
isImplicitDeny[authResults[0].action] = authResults[0].isImplicit;
// second item checks s3:GetObject(Version)Tagging action // second item checks s3:GetObject(Version)Tagging action
if (!authResults[1].isAllowed) { if (!authResults[1].isAllowed) {
log.trace('get tagging authorization denial ' + log.trace('get tagging authorization denial ' +
@ -146,13 +157,25 @@ const api = {
} }
} else { } else {
for (let i = 0; i < authResults.length; i++) { for (let i = 0; i < authResults.length; i++) {
if (!authResults[i].isAllowed) { isImplicitDeny[authResults[i].action] = true;
if (!authResults[i].isAllowed && !authResults[i].isImplicit) {
// Any explicit deny rejects the current API call
log.trace('authorization denial from Vault'); log.trace('authorization denial from Vault');
return errors.AccessDenied; return errors.AccessDenied;
} else if (authResults[i].isAllowed) {
// If the action is allowed, the result is not implicit
// Deny.
isImplicitDeny[authResults[i].action] = false;
isOnlyImplicitDeny = false;
} }
} }
} }
return returnTagCount; // These two APIs cannot use ACLs or Bucket Policies, hence, any
// implicit deny from vault must be treated as an explicit deny.
if ((apiMethod === 'bucketPut' || apiMethod === 'serviceGet') && isOnlyImplicitDeny) {
return errors.AccessDenied;
}
return { returnTagCount, isImplicitDeny };
} }
return async.waterfall([ return async.waterfall([
@ -230,7 +253,16 @@ const api = {
if (checkedResults instanceof Error) { if (checkedResults instanceof Error) {
return callback(checkedResults); return callback(checkedResults);
} }
returnTagCount = checkedResults; returnTagCount = checkedResults.returnTagCount;
request.actionImplicitDenies = checkedResults.isImplicitDeny;
} else {
// create an object of keys apiMethods with all values to false:
// for backward compatibility, all apiMethods are allowed by default
// thus it is explicitly allowed, so implicit deny is false
request.actionImplicitDenies = apiMethods.reduce((acc, curr) => {
acc[curr] = false;
return acc;
}, {});
} }
if (apiMethod === 'objectPut' || apiMethod === 'objectPutPart') { if (apiMethod === 'objectPut' || apiMethod === 'objectPutPart') {
request._response = response; request._response = response;

View File

@ -20,7 +20,7 @@
"homepage": "https://github.com/scality/S3#readme", "homepage": "https://github.com/scality/S3#readme",
"dependencies": { "dependencies": {
"@hapi/joi": "^17.1.0", "@hapi/joi": "^17.1.0",
"arsenal": "git+https://github.com/scality/arsenal#7.10.47", "arsenal": "git+https://github.com/scality/arsenal#df5ff0f4006ee0a21269e139567fd5c425a4225f",
"async": "~2.5.0", "async": "~2.5.0",
"aws-sdk": "2.905.0", "aws-sdk": "2.905.0",
"azure-storage": "^2.1.0", "azure-storage": "^2.1.0",

View File

@ -488,9 +488,9 @@ arraybuffer.slice@~0.0.7:
optionalDependencies: optionalDependencies:
ioctl "^2.0.2" ioctl "^2.0.2"
"arsenal@git+https://github.com/scality/arsenal#7.10.47": "arsenal@git+https://github.com/scality/arsenal#df5ff0f4006ee0a21269e139567fd5c425a4225f":
version "7.10.47" version "7.10.48"
resolved "git+https://github.com/scality/arsenal#3f24336b83581d121f52146b8003e0a68d9ce876" resolved "git+https://github.com/scality/arsenal#df5ff0f4006ee0a21269e139567fd5c425a4225f"
dependencies: dependencies:
"@types/async" "^3.2.12" "@types/async" "^3.2.12"
"@types/utf8" "^3.0.1" "@types/utf8" "^3.0.1"
@ -506,7 +506,7 @@ arraybuffer.slice@~0.0.7:
bson "4.0.0" bson "4.0.0"
debug "~2.6.9" debug "~2.6.9"
diskusage "^1.1.1" diskusage "^1.1.1"
fcntl "github:scality/node-fcntl#0.2.0" fcntl "github:scality/node-fcntl#0.2.2"
hdclient scality/hdclient#1.1.0 hdclient scality/hdclient#1.1.0
https-proxy-agent "^2.2.0" https-proxy-agent "^2.2.0"
ioredis "^4.28.5" ioredis "^4.28.5"
@ -1918,6 +1918,14 @@ fast-levenshtein@~2.0.6:
nan "^2.3.2" nan "^2.3.2"
node-gyp "^8.0.0" node-gyp "^8.0.0"
"fcntl@github:scality/node-fcntl#0.2.2":
version "0.2.1"
resolved "https://codeload.github.com/scality/node-fcntl/tar.gz/b1335ca204c6265cedc50c26020c4d63aabe920e"
dependencies:
bindings "^1.1.1"
nan "^2.3.2"
node-gyp "^8.0.0"
fecha@^4.2.0: fecha@^4.2.0:
version "4.2.3" version "4.2.3"
resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd"