Skip to content

Commit 3b6019c

Browse files
fix(core): Minor Security Enhancements (#704)
* Tighten permissions on: PBMMAccel-CB-Installer role * Tighten VPC interface endpoint security group permissions * fixing SecurityGroupEgress
1 parent da88c5c commit 3b6019c

File tree

4 files changed

+44
-19
lines changed

4 files changed

+44
-19
lines changed

src/deployments/cdk/src/common/interface-endpoints.ts

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ export interface InterfaceEndpointProps {
77
vpcId: string;
88
vpcRegion: string;
99
subnetIds: string[];
10+
allowedCidrs?: string[];
11+
ports?: string[];
12+
}
13+
14+
enum ProtocolPrefix {
15+
TCP = 'TCP:',
16+
UDP = 'UDP:',
17+
ICMP = 'ICMP:',
1018
}
1119

1220
/**
@@ -18,31 +26,44 @@ export class InterfaceEndpoint extends cdk.Construct {
1826
constructor(scope: cdk.Construct, id: string, props: InterfaceEndpointProps) {
1927
super(scope, id);
2028

21-
const { serviceName, vpcId, vpcRegion, subnetIds } = props;
22-
29+
const { serviceName, vpcId, vpcRegion, subnetIds, allowedCidrs, ports } = props;
30+
const securityGroupIngress: ec2.CfnSecurityGroup.IngressProperty[] = [];
31+
for (const ingressCidr of allowedCidrs || ['0.0.0.0/0']) {
32+
for (const endpointPort of ports || ['TCP:443']) {
33+
let ipProtocol: ec2.Protocol;
34+
let port: number;
35+
if (endpointPort.startsWith(ProtocolPrefix.TCP)) {
36+
port = parseInt(endpointPort.split(ProtocolPrefix.TCP).pop()!, 10);
37+
ipProtocol = ec2.Protocol.TCP;
38+
} else if (endpointPort.startsWith(ProtocolPrefix.UDP)) {
39+
port = parseInt(endpointPort.split(ProtocolPrefix.UDP).pop()!, 10);
40+
ipProtocol = ec2.Protocol.UDP;
41+
} else if (endpointPort.startsWith(ProtocolPrefix.ICMP)) {
42+
port = parseInt(endpointPort.split(ProtocolPrefix.ICMP).pop()!, 10);
43+
ipProtocol = ec2.Protocol.ICMP;
44+
} else {
45+
port = 443;
46+
ipProtocol = ec2.Protocol.TCP;
47+
}
48+
securityGroupIngress.push({
49+
ipProtocol,
50+
cidrIp: ingressCidr,
51+
toPort: port,
52+
fromPort: port,
53+
});
54+
}
55+
}
2356
// Create a new security groupo per endpoint
2457
const securityGroup = new ec2.CfnSecurityGroup(this, `ep_${serviceName}`, {
2558
vpcId,
2659
groupDescription: `AWS Private Endpoint Zone - ${serviceName}`,
2760
groupName: `ep_${serviceName}_sg`,
28-
securityGroupIngress: [
29-
{
30-
ipProtocol: ec2.Protocol.ALL,
31-
cidrIp: '0.0.0.0/0',
32-
},
33-
{
34-
ipProtocol: ec2.Protocol.ALL,
35-
cidrIpv6: '0::/0',
36-
},
37-
],
61+
securityGroupIngress,
62+
// Adding Egress '127.0.0.1/32' to avoid default Egress rule
3863
securityGroupEgress: [
3964
{
4065
ipProtocol: ec2.Protocol.ALL,
41-
cidrIp: '0.0.0.0/0',
42-
},
43-
{
44-
ipProtocol: ec2.Protocol.ALL,
45-
cidrIpv6: '0::/0',
66+
cidrIp: '127.0.0.1/32',
4667
},
4768
],
4869
});

src/deployments/cdk/src/deployments/vpc/step-3.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export async function step3(props: VpcStep3Props) {
3131
const allStaticResources = StaticResourcesOutputFinder.findAll({
3232
outputs,
3333
}).filter(sr => sr.resourceType === RESOURCE_TYPE);
34+
const portOverrides = config['global-options']['endpoint-port-orverides'];
3435

3536
const accountStaticResourcesConfig: { [accountKey: string]: StaticResourcesOutput[] } = {};
3637
const accountRegionExistingResources: {
@@ -163,7 +164,6 @@ export async function step3(props: VpcStep3Props) {
163164
console.error(`Cannot find account stack ${accountKey}: ${vpcConfig.region}, while Associating Resolver Rules`);
164165
continue;
165166
}
166-
167167
const interfaceEndpoint = new InterfaceEndpoint(
168168
accountStack,
169169
`Endpoint-${vpcConfig.name}-${pascalCase(endpoint)}`,
@@ -172,6 +172,8 @@ export async function step3(props: VpcStep3Props) {
172172
vpcId: vpcOutput.vpcId,
173173
vpcRegion: vpcConfig.region,
174174
subnetIds: vpcOutput.subnets.filter(sn => sn.subnetName === endpointsConfig.subnet).map(s => s.subnetId),
175+
allowedCidrs: endpointsConfig['allowed-cidrs']?.map(c => c.toCidrString()),
176+
ports: portOverrides?.[endpoint],
175177
},
176178
);
177179

src/installer/cdk/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ async function main() {
122122
installerProjectRole.addToPrincipalPolicy(
123123
new iam.PolicyStatement({
124124
actions: ['sts:AssumeRole'],
125-
resources: [`arn:aws:iam::${cdk.Aws.ACCOUNT_ID}:role/*`],
125+
resources: [`arn:aws:iam::${cdk.Aws.ACCOUNT_ID}:role/cdk-*`],
126126
}),
127127
);
128128

src/lib/common-config/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export const InterfaceEndpointName = t.string; // TODO Define all endpoints here
143143
export const InterfaceEndpointConfig = t.interface({
144144
subnet: t.string,
145145
endpoints: t.array(InterfaceEndpointName),
146+
'allowed-cidrs': optional(t.array(cidr)),
146147
});
147148

148149
export const ResolversConfigType = t.interface({
@@ -857,6 +858,7 @@ export const GlobalOptionsConfigType = t.interface({
857858
'ssm-automation': fromNullable(t.array(SsmAutomation), []),
858859
'aws-config': optional(AwsConfig),
859860
'default-ssm-documents': fromNullable(t.array(t.string), []),
861+
'endpoint-port-orverides': optional(t.record(t.string, t.array(t.string))),
860862
});
861863

862864
export type CentralServicesConfig = t.TypeOf<typeof CentralServicesConfigType>;

0 commit comments

Comments
 (0)