Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/upstream/main' into metrics
Browse files Browse the repository at this point in the history
Merged upstream

Signed-off-by: Brandon Shien <[email protected]>
  • Loading branch information
bshien committed Apr 9, 2024
2 parents a64b4a4 + 7cd8ea1 commit 73e7464
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 38 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/cdk-ci-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: CDK Test

on:
push:
pull_request:

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/[email protected]
with:
node-version: '20.8.0'

- name: Run CDK Test
run: |
cd infrastructure
npm install
npm test
File renamed without changes.
10 changes: 5 additions & 5 deletions infrastructure/lib/constructs/opensearchCognito.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Effect, FederatedPrincipal, ManagedPolicy, PolicyStatement, Role, Servi
import * as cognito from "aws-cdk-lib/aws-cognito";

export interface OpenSearchMetricsCognitoProps {
readonly region: string;
readonly openSearchDomainArn: string;
}

export class OpenSearchMetricsCognito extends Construct {
Expand Down Expand Up @@ -99,16 +99,16 @@ export class OpenSearchMetricsCognito extends Construct {
this.identityPoolAuthRole.addToPolicy(
new PolicyStatement({
effect: Effect.ALLOW,
actions: ['mobileanalytics:PutEvents', 'cognito-sync:*', 'cognito-identity:*', 'es:ESHttp*'],
resources: ['*'],
actions: ["es:ESHttpGet", "es:ESHttpPost"],
resources: [`${props.openSearchDomainArn}`],
}),
);

this.identityPoolAdminRole.addToPolicy(
new PolicyStatement({
effect: Effect.ALLOW,
actions: ['mobileanalytics:PutEvents', 'cognito-sync:*', 'cognito-identity:*', 'es:ESHttp*'],
resources: ['*'],
actions: ["es:ESHttp*", ],
resources: [`${props.openSearchDomainArn}`],
}),
);

Expand Down
38 changes: 26 additions & 12 deletions infrastructure/lib/constructs/opensearchNginxProxyCognito.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
SubnetType,
Vpc,
AmazonLinuxGeneration,
AmazonLinuxImage
AmazonLinuxImage, MachineImage
} from 'aws-cdk-lib/aws-ec2';
import { Effect, ManagedPolicy, PolicyStatement, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam';
import {Aspects, CfnOutput, Duration, Tag, Tags} from 'aws-cdk-lib';
Expand Down Expand Up @@ -49,6 +49,9 @@ export interface opensearchDashboardUrlProps {
}

export class OpenSearchMetricsNginxCognito extends Construct {

static readonly COGNITO_ALB_ARN: string = 'cognitoAlbArn';

readonly asg: AutoScalingGroup;

constructor(scope: Construct, id: string, props: NginxProps) {
Expand All @@ -62,32 +65,39 @@ export class OpenSearchMetricsNginxCognito extends Construct {
instanceType: InstanceType.of(InstanceClass.M5, InstanceSize.LARGE),
blockDevices: [{ deviceName: '/dev/xvda', volume: BlockDeviceVolume.ebs(10) }], // GB
healthCheck: HealthCheck.ec2({ grace: Duration.seconds(90) }),
machineImage: new AmazonLinuxImage({
generation: AmazonLinuxGeneration.AMAZON_LINUX_2,
}),
machineImage: MachineImage.latestAmazonLinux2(),
// Temp added public subnet and IP, until backed up by ALB
associatePublicIpAddress: true,
associatePublicIpAddress: false,
allowAllOutbound: true,
desiredCapacity: 1,
minCapacity: 1,
vpc: props.vpc,
vpcSubnets: {
// Temp added public subnet and IP, until backed up by ALB
// subnetType: SubnetType.PUBLIC,
subnetType: SubnetType.PUBLIC
subnetType: SubnetType.PRIVATE_WITH_EGRESS
},
role: instanceRole,
// Actually update the existing instance instead of leaving it running. This will build a new ASG
// and then destroy the old one in order to maintain availability
updatePolicy: UpdatePolicy.replacingUpdate()
});
Tags.of(this.asg).add("Name", "OpenSearchMetricsCognito")

if (props.albProps) {

const albSecurityGroup = new SecurityGroup(this, 'ALBSecurityGroup', {
vpc,
allowAllOutbound: true,
});
albSecurityGroup.addIngressRule(Peer.prefixList(Project.RESTRICTED_PREFIX), Port.tcp(443));

const openSearchCognitoApplicationLoadBalancer = new ApplicationLoadBalancer(this, `OpenSearchMetricsCognito-NginxProxyAlb`, {
loadBalancerName: "OpenSearchMetricsCognito",
vpc: vpc,
internetFacing: true
internetFacing: true,
securityGroup: albSecurityGroup
});

new CfnOutput(this, 'cognitoAlbArn', {
value: openSearchCognitoApplicationLoadBalancer.loadBalancerArn,
exportName: OpenSearchMetricsNginxCognito.COGNITO_ALB_ARN,
});

const listenerCertificate = ListenerCertificate.fromArn(props.albProps.certificateArn);
Expand All @@ -101,13 +111,17 @@ export class OpenSearchMetricsNginxCognito extends Construct {
listener.addTargets(`OpenSearchMetricsCognito-NginxProxyAlbTarget`, {
port: 443,
protocol: ApplicationProtocol.HTTPS,
healthCheck: {
port: '80',
path: '/',
},
targets: [this.asg]
});


const aRecord = new ARecord(this, "OpenSearchMetricsCognito-DNS", {
zone: props.albProps.hostedZone.zone,
recordName: Project.METRICS_HOSTED_ZONE,
recordName: Project.METRICS_COGNITO_HOSTED_ZONE,
target: RecordTarget.fromAlias(new LoadBalancerTarget(openSearchCognitoApplicationLoadBalancer)),
});
}
Expand Down
2 changes: 1 addition & 1 deletion infrastructure/lib/enums/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ enum Project{
JENKINS_AGENT_ROLE = '',
REGION = '',
METRICS_HOSTED_ZONE = 'metrics.opensearch.org',
// Temp until the project is public
METRICS_COGNITO_HOSTED_ZONE = 'metrics.login.opensearch.org',
RESTRICTED_PREFIX = '',
LAMBDA_PACKAGE = 'opensearch-metrics-1.0.zip',
}
Expand Down
12 changes: 11 additions & 1 deletion infrastructure/lib/infrastructure-stack.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {App, CfnOutput, Stack, StackProps} from 'aws-cdk-lib';
import {App, Fn, Stack, StackProps} from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { VpcStack } from "./stacks/vpc";
import {jenkinsAccess, OpenSearchDomainStack} from "./stacks/opensearch";
Expand All @@ -7,6 +7,8 @@ import {OpenSearchHealthRoute53} from "./stacks/route53";
import {OpenSearchMetricsWorkflowStack} from "./stacks/metricsWorkflow";
import {OpenSearchMetricsNginxReadonly} from "./stacks/opensearchNginxProxyReadonly";
import {ArnPrincipal, IPrincipal} from "aws-cdk-lib/aws-iam";
import {OpenSearchWAF} from "./stacks/waf";
import {OpenSearchMetricsNginxCognito} from "./constructs/opensearchNginxProxyCognito";

// import * as sqs from 'aws-cdk-lib/aws-sqs';
export class InfrastructureStack extends Stack {
Expand Down Expand Up @@ -62,5 +64,13 @@ export class InfrastructureStack extends Stack {
});
openSearchMetricsNginxReadonly.node.addDependency(vpcStack, openSearchDomainStack);

// Create an OpenSearch WAF stack
const openSearchWAF = new OpenSearchWAF(app, "OpenSearchWAF", {
readOnlyLoadBalancerArn: Fn.importValue(`${OpenSearchMetricsNginxReadonly.READONLY_ALB_ARN}`),
cognitoLoadBalancerArn: Fn.importValue(`${OpenSearchMetricsNginxCognito.COGNITO_ALB_ARN}`),
appName: "OpenSearchMetricsWAF"
});
openSearchWAF.node.addDependency(openSearchDomainStack, openSearchMetricsNginxReadonly);

}
}
18 changes: 15 additions & 3 deletions infrastructure/lib/stacks/opensearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { ArnPrincipal, CompositePrincipal, Effect, IRole, ManagedPolicy, PolicyD
import { VpcStack } from "./vpc";
import {OpenSearchMetricsCognito} from "../constructs/opensearchCognito";
import {OpenSearchMetricsNginxCognito} from "../constructs/opensearchNginxProxyCognito";
import {OpenSearchHealthRoute53} from "./route53";
import Project from "../enums/project";



export interface OpenSearchStackProps {
Expand Down Expand Up @@ -53,7 +56,7 @@ export class OpenSearchDomainStack extends Stack {
new PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["sts:AssumeRole"],
resources: ['*'],
resources: [`arn:aws:iam::${props.account}:role/OpenSearchFullAccessRole`],
conditions: {
StringEquals: { 'aws:PrincipalAccount': props.account, 'aws:RequestedRegion': props.region,},
}
Expand All @@ -80,6 +83,7 @@ export class OpenSearchDomainStack extends Stack {
this.fullAccessRole = new Role(this, 'OpenSearchFullAccessRole', {
assumedBy: new CompositePrincipal(...secureRolesList.map((role) => new iam.ArnPrincipal(role.roleArn))),
description: "Master role for OpenSearch full access",
// The Name used in openSearchLambdaRole
roleName: "OpenSearchFullAccessRole",
inlinePolicies: {
"opensearchFullAccess": new PolicyDocument({
Expand All @@ -95,7 +99,7 @@ export class OpenSearchDomainStack extends Stack {
});

const metricsCognito = new OpenSearchMetricsCognito(this, "OpenSearchHealthCognito", {
region: props.region,
openSearchDomainArn: domainArn
});


Expand Down Expand Up @@ -175,14 +179,22 @@ export class OpenSearchDomainStack extends Stack {
this.domain.node.addDependency(serviceLinkedRole);

if(props.enableNginxCognito) {
const metricsHostedZone = new OpenSearchHealthRoute53(this, "OpenSearchMetricsCognito-HostedZone", {
hostedZone: Project.METRICS_COGNITO_HOSTED_ZONE,
appName: "OpenSearchMetricsCognito"
});
new OpenSearchMetricsNginxCognito(this, "OpenSearchMetricsNginx", {
region: this.props.region,
vpc: props.vpcStack.vpc,
securityGroup: props.vpcStack.securityGroup,
opensearchDashboardUrlProps: {
opensearchDashboardVpcUrl: this.domain.domainEndpoint,
cognitoDomain: metricsCognito.userPoolDomain.domain
}
},
albProps: {
hostedZone: metricsHostedZone,
certificateArn: metricsHostedZone.certificateArn,
},
});
}
}
Expand Down
23 changes: 12 additions & 11 deletions infrastructure/lib/stacks/opensearchNginxProxyReadonly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import {
SubnetType,
Vpc,
AmazonLinuxGeneration,
AmazonLinuxImage
AmazonLinuxImage, MachineImage
} from 'aws-cdk-lib/aws-ec2';
import * as iam from "aws-cdk-lib/aws-iam";
import {Aspects, Duration, Stack, Tag, Tags} from 'aws-cdk-lib';
import {Aspects, CfnOutput, Duration, Stack, Tag, Tags} from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {
ApplicationLoadBalancer, ApplicationProtocol,
Expand Down Expand Up @@ -46,6 +46,9 @@ export interface opensearchDashboardUrlProps {
}

export class OpenSearchMetricsNginxReadonly extends Stack {

static readonly READONLY_ALB_ARN: string = 'readOnlyAlbArn';

readonly asg: AutoScalingGroup;

constructor(scope: Construct, id: string, props: NginxProps) {
Expand All @@ -54,15 +57,11 @@ export class OpenSearchMetricsNginxReadonly extends Stack {
super(scope, id);

const instanceRole = this.createNginxReadonlyInstanceRole(props);


this.asg = new AutoScalingGroup(this, 'OpenSearchMetricsReadonly-MetricsProxyAsg', {
instanceType: InstanceType.of(InstanceClass.M5, InstanceSize.LARGE),
blockDevices: [{ deviceName: '/dev/xvda', volume: BlockDeviceVolume.ebs(10) }], // GB
healthCheck: HealthCheck.ec2({ grace: Duration.seconds(90) }),
machineImage: new AmazonLinuxImage({
generation: AmazonLinuxGeneration.AMAZON_LINUX_2,
}),
machineImage: MachineImage.latestAmazonLinux2(),
associatePublicIpAddress: false,
allowAllOutbound: true,
desiredCapacity: 2,
Expand Down Expand Up @@ -90,11 +89,13 @@ export class OpenSearchMetricsNginxReadonly extends Stack {
securityGroup: albSecurityGroup
});

const openSearchWAF = new OpenSearchWAF(this, "OpenSearchWAF", {
loadBalancer: openSearchApplicationLoadBalancer,
appName: "OpenSearchMetricsWAF"
new CfnOutput(this, 'readOnlyAlbArn', {
value: openSearchApplicationLoadBalancer.loadBalancerArn,
exportName: OpenSearchMetricsNginxReadonly.READONLY_ALB_ARN,
});
openSearchWAF.node.addDependency(openSearchApplicationLoadBalancer)

//const importedArnSecretBucketValue = Fn.importValue(`${CIConfigStack.CERTIFICATE_ARN_SECRET_EXPORT_VALUE}`);


const listenerCertificate = ListenerCertificate.fromArn(props.albProps.certificateArn);

Expand Down
13 changes: 9 additions & 4 deletions infrastructure/lib/stacks/waf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,21 @@ export class WebACLAssociation extends CfnWebACLAssociation {
}

export interface WafProps extends StackProps{
loadBalancer: ApplicationLoadBalancer,
readOnlyLoadBalancerArn: string,
cognitoLoadBalancerArn: string
appName: string
}

export class OpenSearchWAF extends Construct {
export class OpenSearchWAF extends Stack {
constructor(scope: Construct, id: string, props: WafProps) {
super(scope, id);
const waf = new WAF(this, `${props.appName}-WAFv2`);
new WebACLAssociation(this, 'wafALBassociation', {
resourceArn: props.loadBalancer.loadBalancerArn,
new WebACLAssociation(this, 'wafReadOnlyALBassociation', {
resourceArn: props.readOnlyLoadBalancerArn,
webAclArn: waf.attrArn,
});
new WebACLAssociation(this, 'wafCognitoALBassociation', {
resourceArn: props.cognitoLoadBalancerArn,
webAclArn: waf.attrArn,
});
}
Expand Down
3 changes: 2 additions & 1 deletion infrastructure/test/vpc-stack.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ test('VPC Stack Test', () => {
]
});

});
});

0 comments on commit 73e7464

Please sign in to comment.