forked from aquasecurity/cloudsploit
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
AkhtarAmir
authored and
AkhtarAmir
committed
Jun 16, 2024
1 parent
8411f25
commit dc8c7a2
Showing
4 changed files
with
310 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
var async = require('async'); | ||
var helpers = require('../../../helpers/aws'); | ||
|
||
module.exports = { | ||
title: 'API Gateway V2 Authorization', | ||
category: 'API Gateway', | ||
domain: 'Availability', | ||
severity: 'High', | ||
description: 'Ensures that Amazon API Gateway V2 APIs are using authorizer.', | ||
more_info: 'API Gateway V2 APIs should be configured to use authorizer to enforce security measures and restrict access to API to only authorized users or processess.', | ||
recommended_action: 'Modify API Gateway V2 configuration and ensure that appropriate authorizers are set up for each API.', | ||
link: 'https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html', | ||
apis: ['ApiGatewayV2:getApis','ApiGatewayV2:getStages'], | ||
realtime_triggers: ['ApiGatewayV2:createApi','ApiGatewayV2:deleteApi','ApiGatewayV2:importApi','ApiGatewayv2:CreateStage','ApiGatewayv2:UpdateStage','ApiGatewayv2:DeleteStage'], | ||
|
||
run: function(cache, settings, callback) { | ||
var results = []; | ||
var source = {}; | ||
var regions = helpers.regions(settings); | ||
var awsOrGov = helpers.defaultPartition(settings); | ||
|
||
async.each(regions.apigatewayv2, function(region, rcb){ | ||
var getApis = helpers.addSource(cache, source, | ||
['apigatewayv2', 'getApis', region]); | ||
|
||
if (!getApis) return rcb(); | ||
|
||
if (getApis.err || !getApis.data) { | ||
helpers.addResult(results, 3, | ||
`Unable to query for API Gateway V2 APIs: ${helpers.addError(getApis)}`, region); | ||
return rcb(); | ||
} | ||
|
||
if (!getApis.data.length) { | ||
helpers.addResult(results, 0, 'No API Gateway V2 APIs found', region); | ||
return rcb(); | ||
} | ||
|
||
getApis.data.forEach(api => { | ||
if (!api.ApiId) return; | ||
|
||
var apiArn = `arn:${awsOrGov}:apigateway:${region}::/apis/${api.ApiId}`; | ||
|
||
var getStages = helpers.addSource(cache, source, | ||
['apigatewayv2', 'getStages', region, api.ApiId]); | ||
|
||
if (!getStages || getStages.err || !getStages.data || !getStages.data.Items) { | ||
helpers.addResult(results, 3, | ||
`Unable to query for API Gateway V2 API Stages: ${helpers.addError(getStages)}`, | ||
region, apiArn); | ||
return; | ||
} | ||
|
||
if (!getStages.data.Items.length) { | ||
helpers.addResult(results, 0, | ||
'No API Gateway V2 API Stages found', | ||
region, apiArn); | ||
return; | ||
} | ||
|
||
getStages.data.Items.forEach(stage => { | ||
if (!stage.StageName) return; | ||
|
||
var stageArn = `arn:${awsOrGov}:apigateway:${region}::/apis/${api.ApiId}/stages/${stage.StageName}`; | ||
if (stage.AccessLogSetting) { | ||
helpers.addResult(results, 0, | ||
'API Gateway V2 API stage has access logging enabled', | ||
region, stageArn); | ||
} else { | ||
helpers.addResult(results, 2, | ||
'API Gateway V2 API stage does not have access logging enabled', | ||
region, stageArn); | ||
} | ||
}); | ||
|
||
}); | ||
|
||
rcb(); | ||
}, function() { | ||
callback(null, results, source); | ||
}); | ||
} | ||
}; | ||
|
||
|
218 changes: 218 additions & 0 deletions
218
plugins/aws/apigateway/apigatewayV2AccessLogging.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
var expect = require('chai').expect; | ||
var apigatewayV2AccessLogging = require('./apigatewayV2AccessLogging'); | ||
|
||
const createCache = (getApis, getStages) => { | ||
if (getApis && getApis.length && getApis[0].ApiId) var restApiId = getApis[0].ApiId; | ||
return { | ||
apigatewayv2: { | ||
getApis: { | ||
'us-east-1': { | ||
data: getApis | ||
} | ||
}, | ||
getStages: { | ||
'us-east-1': { | ||
[restApiId]: { | ||
data: { | ||
Items: getStages | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
}; | ||
|
||
const createErrorCache = () => { | ||
return { | ||
apigatewayv2: { | ||
getApis: { | ||
'us-east-1': { | ||
err: { | ||
message: 'error fetching API Gateway v2 APIs' | ||
}, | ||
}, | ||
}, | ||
getStages: { | ||
'us-east-1': { | ||
err: { | ||
message: 'error fetching API Gateway v2 stages' | ||
}, | ||
}, | ||
} | ||
|
||
}, | ||
}; | ||
}; | ||
|
||
const createUnknownForStage = (api) => { | ||
return { | ||
apigatewayv2: { | ||
getApis: { | ||
'us-east-1': { | ||
data: api | ||
} | ||
}, | ||
getStages: { | ||
'us-east-1': 'err' | ||
} | ||
} | ||
}; | ||
}; | ||
|
||
describe('apigatewayV2AccessLogging', function () { | ||
describe('run', function () { | ||
it('should return UNKNOWN if unable to query for API Gateway v2 APIs', function (done) { | ||
const cache = createErrorCache(); | ||
apigatewayV2AccessLogging.run(cache, {} , (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(3); | ||
expect(results[0].region).to.equal('us-east-1'); | ||
expect (results[0].message).to.include('Unable to query for API Gateway V2 APIs:'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should return PASS if no API Gateway Rest APIs found', function (done) { | ||
const cache = createCache([]); | ||
apigatewayV2AccessLogging.run(cache, {}, (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(0); | ||
expect(results[0].region).to.equal('us-east-1'); | ||
expect (results[0].message).to.include('No API Gateway V2 APIs found'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should return PASS if no stages found', function (done) { | ||
const getApis = [ | ||
{ | ||
ApiId: 'api-id', | ||
name: 'TestAPI', | ||
description: 'Test API', | ||
createdDate: 1621916018, | ||
apiKeySource: 'HEADER', | ||
endpointConfiguration: { | ||
types: ['REGIONAL'] | ||
} | ||
} | ||
]; | ||
const getStages = []; | ||
const cache = createCache(getApis, getStages); | ||
apigatewayV2AccessLogging.run(cache,{}, (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(0); | ||
expect(results[0].region).to.equal('us-east-1'); | ||
expect (results[0].message).to.include('No API Gateway V2 API Stages found'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should return PASS if Api gateway v2 stage has access logging enabled', function (done) { | ||
const getApis = [ | ||
{ | ||
ApiId: 'api-id', | ||
name: 'TestAPI', | ||
description: 'Test API', | ||
createdDate: 1621916018, | ||
apiKeySource: 'HEADER', | ||
endpointConfiguration: { | ||
types: ['REGIONAL'] | ||
} | ||
} | ||
]; | ||
const getStages = [ | ||
{ | ||
"AutoDeploy": true, | ||
"CreatedDate": "2023-12-11T20:07:28.000Z", | ||
"DefaultRouteSettings": { | ||
"DetailedMetricsEnabled": false | ||
}, | ||
"DeploymentId": "biw5qf", | ||
"Description": "Created by AWS Lambda", | ||
"LastDeploymentStatusMessage": "Successfully deployed stage with deployment ID 'biw5qf'", | ||
"LastUpdatedDate": "2023-12-11T20:07:29.000Z", | ||
"RouteSettings": {}, | ||
"StageName": "default", | ||
"StageVariables": {}, | ||
"Tags": {}, | ||
"AccessLogSetting": { | ||
"LogArn": "arn:aws:1234:log" | ||
} | ||
} | ||
]; | ||
const cache = createCache(getApis, getStages); | ||
apigatewayV2AccessLogging.run(cache,{}, (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(0); | ||
expect(results[0].region).to.equal('us-east-1'); | ||
expect(results[0].message).to.include('API Gateway V2 API stage has access logging enabled') | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should return PASS if Api gateway v2 stage has access logging enabled', function (done) { | ||
const getApis = [ | ||
{ | ||
ApiId: 'api-id', | ||
name: 'TestAPI', | ||
description: 'Test API', | ||
createdDate: 1621916018, | ||
apiKeySource: 'HEADER', | ||
endpointConfiguration: { | ||
types: ['REGIONAL'] | ||
} | ||
} | ||
]; | ||
const getStages = [ | ||
{ | ||
"AutoDeploy": true, | ||
"CreatedDate": "2023-12-11T20:07:28.000Z", | ||
"DefaultRouteSettings": { | ||
"DetailedMetricsEnabled": false | ||
}, | ||
"DeploymentId": "biw5qf", | ||
"Description": "Created by AWS Lambda", | ||
"LastDeploymentStatusMessage": "Successfully deployed stage with deployment ID 'biw5qf'", | ||
"LastUpdatedDate": "2023-12-11T20:07:29.000Z", | ||
"RouteSettings": {}, | ||
"StageName": "default", | ||
"StageVariables": {}, | ||
"Tags": {}, | ||
} | ||
]; | ||
const cache = createCache(getApis, getStages); | ||
apigatewayV2AccessLogging.run(cache,{}, (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(2); | ||
expect(results[0].region).to.equal('us-east-1'); | ||
expect(results[0].message).to.include('API Gateway V2 API stage does not have access logging enabled') | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should return UNKNOWN if unable to query for api stages', function (done) { | ||
const getApis = [ | ||
{ | ||
ApiId: 'api-id', | ||
name: 'TestAPI', | ||
description: 'Test API', | ||
createdDate: 1621916018, | ||
apiKeySource: 'HEADER', | ||
endpointConfiguration: { | ||
types: ['REGIONAL'] | ||
} | ||
} | ||
]; | ||
|
||
const cache = createUnknownForStage(getApis); | ||
apigatewayV2AccessLogging.run(cache,{}, (err, results) => { | ||
expect(results.length).to.equal(1); | ||
expect(results[0].status).to.equal(3); | ||
expect(results[0].region).to.equal('us-east-1'); | ||
expect(results[0].message).to.include('Unable to query for API Gateway V2 API Stages:') | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); |