Create a gist now

Instantly share code, notes, and snippets.

Update an AWS Security Group to allow access by a specific AWS service.
'use strict';
const AWS = require('aws-sdk');
const https = require('https');
const ec2 = new AWS.EC2();
const ipRangesUrl = 'https://ip-ranges.amazonaws.com/ip-ranges.json';
const target = {
port: 5432,
protocol: 'tcp',
region: 'ap-southeast-2',
securityGroupId: 'sg-12345678',
service: 'EC2'
};
const getIngressRules = () => {
return new Promise((resolve, reject) => {
console.log(`Getting SG Ingress rules for ${target.securityGroupId}`);
let params = { GroupIds: [ target.securityGroupId ] };
ec2.describeSecurityGroups(params, (err, data) => {
if (err) return reject(err);
return resolve(data);
});
});
};
// Remove all given SG Ingress rules
const removeIngressRules = (data) => {
return new Promise((resolve, reject) => {
let params = data.SecurityGroups[0];
if (params.IpPermissions.length > 0) {
console.log(`Removing ${params.IpPermissions.length} ingress rules`);
// Convert describeSecurityGroups to revokeSecurityGroupIngress format.
delete params.OwnerId;
delete params.Description;
delete params.IpPermissionsEgress;
delete params.VpcId;
delete params.Tags;
delete params.IpPermissions[0].PrefixListIds;
delete params.IpPermissions[0].UserIdGroupPairs;
ec2.revokeSecurityGroupIngress(params, (err) => {
if (err) return reject(err);
return resolve();
});
} else {
console.log('No ingress rules found');
return resolve();
}
});
};
// Get IP ranges from AWS
const getIpRanges = () => {
return new Promise((resolve, reject) => {
https.get('https://ip-ranges.amazonaws.com/ip-ranges.json', (response) => {
let data = '';
response.setEncoding('utf8');
response.on('data', (d) => { data += d; });
response.on('error', (e) => { return reject(e); });
response.on('end', () => {
return resolve(JSON.parse(data));
});
});
});
};
// Convert an IP range object to a SG Ingress Rule.
const toRule = (rangeObject) => {
return {
FromPort: target.port,
ToPort: target.port,
IpProtocol: target.protocol,
IpRanges: [
{
CidrIp: rangeObject.ip_prefix,
}
]
};
};
// Add Ingress Rules to SG
const addIngressRules = (ipRanges) => {
return new Promise((resolve, reject) => {
const rules = ipRanges.
prefixes.
filter((i) => {
return i.service === target.service && i.region === target.region;
}).
map(toRule);
const params = { GroupId: target.securityGroupId, IpPermissions: rules };
console.log(`Adding ${rules.length} ingress rules (as one rule)`);
ec2.authorizeSecurityGroupIngress(params, (err, data) => {
if (err) return reject(err);
return resolve();
});
});
};
exports.handle = (event, context) => {
getIngressRules(target.securityGroupId).
then(removeIngressRules).
then(getIpRanges).
then(addIngressRules).
then(() => { context.succeed(true); }).
catch((err) => { context.fail(err); });
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment