Skip to content

Commit

Permalink
Merge pull request #2055 from AkhtarAmir/M/Aws/Api-gateway-v2-authorizer
Browse files Browse the repository at this point in the history
M/Aws/Api-gateway-v2-authorizer
  • Loading branch information
alphadev4 authored Jun 20, 2024
2 parents 5169d9e + 1042338 commit 3284f67
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 0 deletions.
1 change: 1 addition & 0 deletions exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module.exports = {
'customDomainTlsVersion' : require(__dirname + '/plugins/aws/apigateway/customDomainTlsVersion.js'),
'apigatewayDefaultEndpointDisabled' : require(__dirname + '/plugins/aws/apigateway/apigatewayDefaultEndpointDisabled.js'),
'apigatewayAuthorization' : require(__dirname + '/plugins/aws/apigateway/apigatewayAuthorization.js'),
'apigatewayV2Authorization' : require(__dirname + '/plugins/aws/apigateway/apigatewayV2Authorization.js'),
'apigatewayRequestValidation' : require(__dirname + '/plugins/aws/apigateway/apigatewayRequestValidation.js'),

'restrictExternalTraffic' : require(__dirname + '/plugins/aws/appmesh/restrictExternalTraffic.js'),
Expand Down
14 changes: 14 additions & 0 deletions helpers/aws/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,12 @@ var calls = {
paginate: 'NextToken'
}
},
ApiGatewayV2: {
getApis: {
property: 'Items',
paginate: 'NextToken'
},
},
AppConfig: {
listApplications: {
property: 'Items',
Expand Down Expand Up @@ -1853,6 +1859,14 @@ var postcalls = [
filterValue: 'id'
}
},
ApiGatewayV2: {
getAuthorizers: {
reliesOnService: 'apigatewayv2',
reliesOnCall: 'getApis',
filterKey: 'ApiId',
filterValue: 'ApiId'
}
},
AppConfig: {
listConfigurationProfiles: {
reliesOnService: 'appconfig',
Expand Down
1 change: 1 addition & 0 deletions helpers/aws/regions.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ module.exports = {
accessanalyzer: [...regions, ...newRegionsUpdate],
acm: [...regions, ...newRegionsUpdate],
apigateway: [...regions, ...newRegionsUpdate],
apigatewayv2: [...regions, ...newRegionsUpdate],
athena:[...regions, ...newRegionsUpdate],
bedrock: ['us-east-1', 'us-west-2', 'ap-south-1','ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'eu-central-1', 'eu-west-1', 'eu-west-3'],
cloudfront: ['us-east-1'], // CloudFront uses the default global region
Expand Down
1 change: 1 addition & 0 deletions helpers/aws/regions_china.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module.exports = {
cognitoidentityserviceprovider: regions,
acm: [],
apigateway: regions,
apigatewayv2: regions,
athena: [],
bedrock:[],
cloudfront: [],
Expand Down
1 change: 1 addition & 0 deletions helpers/aws/regions_gov.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports = {
accessanalyzer: regions,
acm: regions,
apigateway: regions,
apigatewayv2: regions,
athena: regions,
backup: regions,
bedrock: ['us-gov-west-1'],
Expand Down
73 changes: 73 additions & 0 deletions plugins/aws/apigateway/apigatewayV2Authorization.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
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 processes.',
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:getAuthorizers'],
realtime_triggers: ['ApiGatewayV2:createApi','ApiGatewayV2:deleteApi','ApiGatewayV2:importApi','ApiGatewayV2:createAuthorizer','ApiGatewayV2:deleteAuthorizer'],

run: function(cache, settings, callback) {
console.log('here');
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 getAuthorizers = helpers.addSource(cache, source,
['apigatewayv2', 'getAuthorizers', region, api.ApiId]);

if (!getAuthorizers || getAuthorizers.err || !getAuthorizers.data || !getAuthorizers.data.Items) {
helpers.addResult(results, 3,
`Unable to query for API Gateway V2 authorizers: ${helpers.addError(getAuthorizers)}`,
region, apiArn);
return;
}

if (!getAuthorizers.data.Items.length) {
helpers.addResult(results, 2,
'No authorizers found for API Gateway V2 API',
region, apiArn );
} else {
helpers.addResult(results, 0,
'Authorizers found for API Gateway V2 API',
region, apiArn);
}
});

rcb();
}, function() {
callback(null, results, source);
});
}
};


157 changes: 157 additions & 0 deletions plugins/aws/apigateway/apigatewayV2Authorization.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
var expect = require('chai').expect;
var apigatewayV2Authorization = require('./apigatewayV2Authorization');

const createCache = (getApis, getAuthorizersData) => {
if (getApis && getApis.length && getApis[0].ApiId) var restApiId = getApis[0].ApiId;
return {
apigatewayv2: {
getApis: {
'us-east-1': {
data: getApis
}
},
getAuthorizers: {
'us-east-1': {
[restApiId]: {
data: {
Items: getAuthorizersData
}
}
}
}
}
};
};

const createErrorCache = () => {
return {
apigatewayv2: {
getApis: {
'us-east-1': {
err: {
message: 'error fetching API Gateway v2 APIs'
},
},
},
getAuthorizers: {
'us-east-1': {
err: {
message: 'error fetching API Gateway v2 Authorizers'
},
},
}

},
};
};

const createNullCache = () => {
return {
apigatewayv2: {
getApis: {
'us-east-1': null
},
getAuthorizers: {
'us-east-1': null
}
}
};
};

describe('apigatewayV2Authorization', function () {
describe('run', function () {
it('should return UNKNOWN if unable to query for API Gateway v2 APIs', function (done) {
const cache = createErrorCache();
apigatewayV2Authorization.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([]);
apigatewayV2Authorization.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 FAIL if no authorizers exist for API Gateway Rest API', function (done) {
const getApis = [
{
ApiId: 'api-id',
name: 'TestAPI',
description: 'Test API',
createdDate: 1621916018,
apiKeySource: 'HEADER',
endpointConfiguration: {
types: ['REGIONAL']
}
}
];
const getAuthorizersData = [];
const cache = createCache(getApis, getAuthorizersData);
apigatewayV2Authorization.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('No authorizers found for API Gateway V2 API');
done();
});
});

it('should return PASS if authorizers exist for API Gateway V2 API', function (done) {
const getApis = [
{
ApiId: 'api-id',
name: 'TestAPI',
description: 'Test API',
createdDate: 1621916018,
apiKeySource: 'HEADER',
endpointConfiguration: {
types: ['REGIONAL']
}
}
];
const getAuthorizersData = [
{
name: 'authorizer1',
type: 'REQUEST',
authType: 'custom',
authorizerUri: 'arn:aws:lambda:us-east-1:123456789012:function:authorizer1',
identitySource: 'method.request.header.Authorization',
authorizerResultTtlInSeconds: 300
},
{
name: 'authorizer2',
type: 'REQUEST',
authType: 'custom',
authorizerUri: 'arn:aws:lambda:us-east-1:123456789012:function:authorizer2',
identitySource: 'method.request.header.Authorization',
authorizerResultTtlInSeconds: 300
}
];
const cache = createCache(getApis, getAuthorizersData);
apigatewayV2Authorization.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('Authorizers found for API Gateway V2 API')
done();
});
});
it('should not return anything if get Rest APIs response is not found', function (done) {
const cache = createNullCache();
apigatewayV2Authorization.run(cache, {}, (err, results) => {
expect(results.length).to.equal(0);
done();
});
});
});
});

0 comments on commit 3284f67

Please sign in to comment.