diff --git a/lib/api/api.js b/lib/api/api.js index fae6343eee..f7dc8ae6e3 100644 --- a/lib/api/api.js +++ b/lib/api/api.js @@ -117,6 +117,7 @@ const api = { // no need to check auth on website or cors preflight requests if (apiMethod === 'websiteGet' || apiMethod === 'websiteHead' || apiMethod === 'corsPreflight') { + request.actionImplicitDenies = false; return this[apiMethod](request, log, callback); } @@ -139,15 +140,25 @@ const api = { const requestContexts = prepareRequestContexts(apiMethod, request, 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) { let returnTagCount = true; + const isImplicitDeny = {}; + let isOnlyImplicitDeny = true; if (apiMethod === 'objectGet') { // 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'); 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 if (!authResults[1].isAllowed) { log.trace('get tagging authorization denial ' + @@ -156,13 +167,25 @@ const api = { } } else { 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'); 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([ @@ -243,7 +266,16 @@ const api = { if (checkedResults instanceof Error) { 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') { request._response = response; diff --git a/package.json b/package.json index e618fd9e32..8a19bf5199 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "@azure/storage-blob": "^12.12.0", "@hapi/joi": "^17.1.0", - "arsenal": "git+https://github.com/scality/arsenal#8.1.112", + "arsenal": "git+https://github.com/scality/arsenal#8.1.114", "async": "~2.5.0", "aws-sdk": "2.905.0", "bucketclient": "scality/bucketclient#8.1.9", diff --git a/yarn.lock b/yarn.lock index ad65b49ea8..f1e67610f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -729,9 +729,9 @@ arraybuffer.slice@~0.0.7: optionalDependencies: ioctl "^2.0.2" -"arsenal@git+https://github.com/scality/arsenal#8.1.112": - version "8.1.112" - resolved "git+https://github.com/scality/arsenal#af345717716402c828a2f117a932fef6c58c9f7a" +"arsenal@git+https://github.com/scality/arsenal#8.1.114": + version "8.1.114" + resolved "git+https://github.com/scality/arsenal#7866a1d06fa6b51faf81dad24481cc735c010adf" dependencies: "@azure/identity" "^3.1.1" "@azure/storage-blob" "^12.12.0"