@@ -11,10 +11,13 @@ const { onlyOwnerAllowed } = require('../../constants');
1111const { actionNeedQuotaCheck, actionWithDataDeletion } = require ( 'arsenal/build/lib/policyEvaluator/RequestContext' ) ;
1212const { processBytesToWrite, validateQuotas } = require ( '../api/apiUtils/quotas/quotaUtils' ) ;
1313const { config } = require ( '../Config' ) ;
14+ const cache = require ( '../api/apiUtils/rateLimit/cache' ) ;
1415const {
15- extractAndCacheRateLimitConfig,
16- checkRateLimitWithConfig,
1716 rateLimitApiActions,
17+ requestNeedsRateCheck,
18+ extractRateLimitConfigFromRequest,
19+ buildRateChecksFromConfig,
20+ checkRateLimitsForRequest,
1821} = require ( '../api/apiUtils/rateLimit/helpers' ) ;
1922
2023/**
@@ -242,67 +245,68 @@ function validateBucket(bucket, params, log, actionImplicitDenies = {}) {
242245 * Extracts rate limit config from bucket metadata, caches it, and enforces limit.
243246 * Calls callback with error if rate limited, null if allowed or no rate limiting.
244247 *
245- * @param {object } bucket - Bucket metadata object
246- * @param {string } bucketName - Bucket name
247- * @param {object } request - Request object with rateLimitAlreadyChecked tracker
248+ * @param {object } request - Request object
249+ * @param {AuthInfo } authInfo - AuthInfo class instance, requester's info
250+ * @param {BucketInfo } bucketMD - Bucket metadata
248251 * @param {object } log - Logger instance
249252 * @param {function } callback - Callback(err) - err if rate limited, null if allowed
250253 * @returns {undefined }
251254 */
252- function checkRateLimitIfNeeded ( bucket , bucketName , request , log , callback ) {
255+ function checkRateLimitIfNeeded ( request , authInfo , bucketMD , log , callback ) {
253256 // Skip if already checked or not enabled
254- if ( request . rateLimitAlreadyChecked
255- || ! config . rateLimiting ?. enabled
256- || rateLimitApiActions . includes ( request . apiMethod )
257- || request . isInternalServiceRequest ) {
257+ if ( ! requestNeedsRateCheck ( request ) ) {
258258 return process . nextTick ( callback , null ) ;
259259 }
260260
261261 // Extract rate limit config from bucket metadata and cache it
262- const rateLimitConfig = extractAndCacheRateLimitConfig ( bucket , bucketName , log ) ;
262+ const checks = [ ] ;
263+ const rateLimitConfig = extractRateLimitConfigFromRequest ( request , authInfo , bucketMD , log ) ;
263264
264- // No rate limiting configured
265- if ( ! rateLimitConfig ) {
265+ if ( ! request . rateLimitBucketAlreadyChecked && rateLimitConfig . bucket !== undefined ) {
266+ cache . setCachedConfig (
267+ cache . namespace . bucket ,
268+ bucketMD . getName ( ) ,
269+ rateLimitConfig . bucket ,
270+ config . rateLimiting . bucket . configCacheTTL
271+ ) ;
272+ cache . setCachedBucketOwner ( bucketMD . getName ( ) , bucketMD . getOwner ( ) , config . rateLimiting . bucket . configCacheTTL ) ;
273+ checks . push ( ...buildRateChecksFromConfig ( 'bucket' , bucketMD . getName ( ) , rateLimitConfig . bucket ) ) ;
266274 // eslint-disable-next-line no-param-reassign
267- request . rateLimitAlreadyChecked = true ;
268- return process . nextTick ( callback , null ) ;
275+ request . rateLimitBucketAlreadyChecked = true ;
269276 }
270277
271- // Check rate limit with GCRA
272- return checkRateLimitWithConfig (
273- bucketName ,
274- rateLimitConfig ,
275- log ,
276- ( rateLimitErr , rateLimited ) => {
277- if ( rateLimitErr ) {
278- log . error ( 'Rate limit check error in metadata validation ', {
279- error : rateLimitErr ,
280- } ) ;
281- }
278+ if ( ! request . rateLimitAccountAlreadyChecked && rateLimitConfig . account !== undefined ) {
279+ cache . setCachedConfig (
280+ cache . namespace . account ,
281+ authInfo . getCanonicalID ( ) ,
282+ rateLimitConfig . account ,
283+ config . rateLimiting . account . configCacheTTL
284+ ) ;
285+ checks . push ( ... buildRateChecksFromConfig ( 'account ', authInfo . getCanonicalID ( ) , rateLimitConfig . account ) ) ;
286+ // eslint-disable-next-line no-param-reassign
287+ request . rateLimitAccountAlreadyChecked = true ;
288+ }
282289
283- if ( rateLimited ) {
284- log . addDefaultFields ( {
285- rateLimited : true ,
286- rateLimitSource : rateLimitConfig . source ,
287- } ) ;
288- // Add to server access log
289- /* eslint-disable no-param-reassign */
290- if ( request . serverAccessLog ) {
291- request . serverAccessLog . rateLimited = true ;
292- request . serverAccessLog . rateLimitSource = rateLimitConfig . source ;
293- }
294- request . rateLimitAlreadyChecked = true ;
295- /* eslint-enable no-param-reassign */
296- return callback ( config . rateLimiting . error ) ;
297- }
290+ const { allowed, rateLimitSource } = checkRateLimitsForRequest ( checks , log ) ;
291+ if ( ! allowed ) {
292+ log . addDefaultFields ( {
293+ rateLimited : true ,
294+ rateLimitSource,
295+ } ) ;
298296
299- // Allowed - set tracker and continue
300- // eslint-disable-next-line no-param-reassign
301- request . rateLimitAlreadyChecked = true ;
302- return callback ( null ) ;
297+ if ( request . serverAccessLog ) {
298+ /* eslint-disable no-param-reassign */
299+ request . serverAccessLog . rateLimited = true ;
300+ request . serverAccessLog . rateLimitSource = rateLimitSource ;
301+ /* eslint-enable no-param-reassign */
303302 }
304- ) ;
303+
304+ return process . nextTick ( callback , config . rateLimiting . error ) ;
305+ }
306+
307+ return process . nextTick ( callback , null ) ;
305308}
309+
306310/** standardMetadataValidateBucketAndObj - retrieve bucket and object md from metadata
307311 * and check if user is authorized to access them.
308312 * @param {object } params - function parameters
@@ -362,7 +366,7 @@ function standardMetadataValidateBucketAndObj(params, actionImplicitDenies, log,
362366 }
363367
364368 // Rate limiting check if not already done in api.js
365- return checkRateLimitIfNeeded ( bucket , bucketName , request , log , err => {
369+ return checkRateLimitIfNeeded ( request , authInfo , bucket , log , err => {
366370 if ( err ) {
367371 return next ( err , bucket ) ;
368372 }
@@ -456,7 +460,7 @@ function standardMetadataValidateBucket(params, actionImplicitDenies, log, callb
456460 }
457461
458462 // Rate limiting check if not already done in api.js
459- return checkRateLimitIfNeeded ( bucket , bucketName , request , log , err => {
463+ return checkRateLimitIfNeeded ( request , params . authInfo , bucket , log , err => {
460464 if ( err ) {
461465 return callback ( err ) ;
462466 }
0 commit comments