Skip to content

Commit

Permalink
Merge pull request #378 from guardian/aa-sg-app-identity
Browse files Browse the repository at this point in the history
feat: allow GuSecurityGroup to be specified at the app level
  • Loading branch information
akash1810 authored Apr 6, 2021
2 parents b7b7936 + 598f226 commit 6c6dadd
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 20 deletions.
15 changes: 8 additions & 7 deletions src/constructs/autoscaling/asg.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,12 @@ describe("The GuAutoScalingGroup", () => {
});

test("adds any security groups passed through props", () => {
const app = "Testing";
const stack = simpleGuStackForTesting();

const securityGroup = new GuSecurityGroup(stack, "SecurityGroup", { vpc, overrideId: true });
const securityGroup1 = new GuSecurityGroup(stack, "SecurityGroup1", { vpc, overrideId: true });
const securityGroup2 = new GuSecurityGroup(stack, "SecurityGroup2", { vpc, overrideId: true });
const securityGroup = new GuSecurityGroup(stack, "SecurityGroup", { vpc, overrideId: true, app });
const securityGroup1 = new GuSecurityGroup(stack, "SecurityGroup1", { vpc, overrideId: true, app });
const securityGroup2 = new GuSecurityGroup(stack, "SecurityGroup2", { vpc, overrideId: true, app });

new GuAutoScalingGroup(stack, "AutoscalingGroup", {
...defaultProps,
Expand All @@ -136,16 +137,16 @@ describe("The GuAutoScalingGroup", () => {
expect(stack).toHaveResource("AWS::AutoScaling::LaunchConfiguration", {
SecurityGroups: [
{
"Fn::GetAtt": ["GuHttpsEgressSecurityGroupF63CDA96", "GroupId"],
"Fn::GetAtt": [`GuHttpsEgressSecurityGroup${app}89CDDA4B`, "GroupId"],
},
{
"Fn::GetAtt": ["SecurityGroup", "GroupId"],
"Fn::GetAtt": [`SecurityGroup${app}`, "GroupId"],
},
{
"Fn::GetAtt": ["SecurityGroup1", "GroupId"],
"Fn::GetAtt": [`SecurityGroup1${app}`, "GroupId"],
},
{
"Fn::GetAtt": ["SecurityGroup2", "GroupId"],
"Fn::GetAtt": [`SecurityGroup2${app}`, "GroupId"],
},
],
});
Expand Down
12 changes: 8 additions & 4 deletions src/constructs/ec2/security-groups/base.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ describe("The GuSecurityGroup class", () => {
it("overrides the id if the prop is set to true", () => {
const stack = simpleGuStackForTesting();

new GuSecurityGroup(stack, "TestSecurityGroup", { vpc, overrideId: true });
new GuSecurityGroup(stack, "TestSecurityGroup", { vpc, overrideId: true, app: "testing" });

const json = SynthUtils.toCloudFormation(stack) as SynthedStack;
expect(Object.keys(json.Resources)).toContain("TestSecurityGroup");
expect(Object.keys(json.Resources)).toContain("TestSecurityGroupTesting");
});

it("does not overrides the id if the prop is set to false", () => {
const stack = simpleGuStackForTesting();

new GuSecurityGroup(stack, "TestSecurityGroup", { vpc });
new GuSecurityGroup(stack, "TestSecurityGroup", { vpc, app: "testing" });

const json = SynthUtils.toCloudFormation(stack) as SynthedStack;
expect(Object.keys(json.Resources)).not.toContain("TestSecurityGroup");
Expand All @@ -40,6 +40,7 @@ describe("The GuSecurityGroup class", () => {
{ range: Peer.ipv4("127.0.0.1/24"), description: "ingress1", port: 443 },
{ range: Peer.ipv4("127.0.0.2/8"), description: "ingress2", port: 443 },
],
app: "testing",
});

expect(stack).toHaveResource("AWS::EC2::SecurityGroup", {
Expand Down Expand Up @@ -72,6 +73,7 @@ describe("The GuSecurityGroup class", () => {
{ range: Peer.ipv4("127.0.0.1/24"), port: Port.tcp(8000), description: "egress1" },
{ range: Peer.ipv4("127.0.0.2/8"), port: Port.tcp(9000), description: "egress2" },
],
app: "testing",
});

expect(stack).toHaveResource("AWS::EC2::SecurityGroup", {
Expand Down Expand Up @@ -101,6 +103,7 @@ describe("The GuSecurityGroup class", () => {
new GuSecurityGroup(stack, "TestSecurityGroup", {
vpc,
ingresses: [{ range: Peer.anyIpv4(), description: "SSH access", port: 22 }],
app: "testing",
});
}).toThrow(new Error("An ingress rule on port 22 is not allowed. Prefer to setup SSH via SSM."));
});
Expand All @@ -118,6 +121,7 @@ describe("The GuPublicInternetAccessSecurityGroup class", () => {

new GuPublicInternetAccessSecurityGroup(stack, "InternetAccessGroup", {
vpc,
app: "testing",
});

expect(stack).toHaveResource("AWS::EC2::SecurityGroup", {
Expand Down Expand Up @@ -145,7 +149,7 @@ describe("The GuHttpsEgressSecurityGroup class", () => {
it("adds global access on 443 by default", () => {
const stack = simpleGuStackForTesting();

GuHttpsEgressSecurityGroup.forVpc(stack, { vpc });
GuHttpsEgressSecurityGroup.forVpc(stack, { vpc, app: "testing" });

expect(stack).toHaveResource("AWS::EC2::SecurityGroup", {
GroupDescription: "Allow all outbound HTTPS traffic",
Expand Down
27 changes: 20 additions & 7 deletions src/constructs/ec2/security-groups/base.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { CfnSecurityGroup, IPeer, SecurityGroupProps } from "@aws-cdk/aws-ec2";
import { Peer, Port, SecurityGroup } from "@aws-cdk/aws-ec2";
import type { GuStack } from "../../core";
import { AppIdentity } from "../../core/identity";

/**
* A way to describe an ingress or egress rule for a security group.
Expand All @@ -27,12 +28,14 @@ export interface SecurityGroupAccessRule {
description: string;
}

export interface GuSecurityGroupProps extends SecurityGroupProps {
export interface GuBaseSecurityGroupProps extends SecurityGroupProps {
overrideId?: boolean;
ingresses?: SecurityGroupAccessRule[];
egresses?: SecurityGroupAccessRule[];
}

export interface GuSecurityGroupProps extends GuBaseSecurityGroupProps, AppIdentity {}

/**
* Defining an AWS Security Group with ingress and egress rules.
*
Expand All @@ -43,8 +46,8 @@ export interface GuSecurityGroupProps extends SecurityGroupProps {
* - [[GuPublicInternetAccessSecurityGroup]]
* - [[GuHttpsEgressSecurityGroup]]
*/
export class GuSecurityGroup extends SecurityGroup {
constructor(scope: GuStack, id: string, props: GuSecurityGroupProps) {
export abstract class GuBaseSecurityGroup extends SecurityGroup {
protected constructor(scope: GuStack, id: string, props: GuBaseSecurityGroupProps) {
super(scope, id, props);

if (props.overrideId) {
Expand All @@ -68,8 +71,16 @@ export class GuSecurityGroup extends SecurityGroup {
}
}

export class GuSecurityGroup extends GuBaseSecurityGroup {
constructor(scope: GuStack, id: string, props: GuSecurityGroupProps) {
super(scope, AppIdentity.suffixText(props, id), props);
AppIdentity.taggedConstruct(props, this);
}
}

// TODO should this be a singleton?
export class GuPublicInternetAccessSecurityGroup extends GuSecurityGroup {
constructor(scope: GuStack, id: string, props: SecurityGroupProps) {
constructor(scope: GuStack, id: string, props: GuSecurityGroupProps) {
super(scope, id, {
...props,
ingresses: [{ range: Peer.anyIpv4(), port: 443, description: "Allow all inbound traffic via HTTPS" }],
Expand All @@ -78,17 +89,19 @@ export class GuPublicInternetAccessSecurityGroup extends GuSecurityGroup {
}
}

// TODO should this be a singleton?
export class GuHttpsEgressSecurityGroup extends GuSecurityGroup {
constructor(scope: GuStack, id: string, props: SecurityGroupProps) {
constructor(scope: GuStack, id: string, props: GuSecurityGroupProps) {
super(scope, id, {
vpc: props.vpc,
...props,
allowAllOutbound: false,
description: "Allow all outbound HTTPS traffic",
ingresses: [],
egresses: [{ range: Peer.anyIpv4(), port: 443, description: "Allow all outbound HTTPS traffic" }],
});
}

public static forVpc(scope: GuStack, props: SecurityGroupProps): GuHttpsEgressSecurityGroup {
public static forVpc(scope: GuStack, props: GuSecurityGroupProps): GuHttpsEgressSecurityGroup {
return new GuHttpsEgressSecurityGroup(scope, "GuHttpsEgressSecurityGroup", props);
}
}
4 changes: 2 additions & 2 deletions src/constructs/ec2/security-groups/wazuh.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { IVpc } from "@aws-cdk/aws-ec2";
import { Peer } from "@aws-cdk/aws-ec2";
import type { GuStack } from "../../core";
import { GuSecurityGroup } from "./base";
import { GuBaseSecurityGroup } from "./base";

export class GuWazuhAccess extends GuSecurityGroup {
export class GuWazuhAccess extends GuBaseSecurityGroup {
private static instance: GuWazuhAccess | undefined;

private constructor(scope: GuStack, vpc: IVpc) {
Expand Down

0 comments on commit 6c6dadd

Please sign in to comment.