Skip to content

Commit

Permalink
VA-411-1-3: Use just one load balancer and do the hostname based rout…
Browse files Browse the repository at this point in the history
…ing there (virkailija vs. hakija)
  • Loading branch information
anttu committed Jun 6, 2024
1 parent a2b9040 commit 43a4190
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 49 deletions.
13 changes: 13 additions & 0 deletions cdk/bin/cdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ const HAKIJA_DOMAIN = 'valtionavustukset.oph.fi'
const HAKIJA_DOMAIN_SV = 'statsunderstod.oph.fi'
const VIRKAILIJA_DOMAIN = 'virkailija.valtionavustukset.oph.fi'

/* Use prefix so we can access the services in AWS during development, as the above hostnames are already used by CSC by current production servers
* for example:
* aws.dev.valtionavustukset.oph.fi
* aws.dev.virkailija.valtionavustukset.oph.fi
* This can be removed or set to empty string once we want to go live and stop using CSC servers in production
* */
export const AWS_SERVICE_PREFIX = 'aws.'
const LEGACY_LOADBALANCER_IP = '86.50.28.144'

const app = new cdk.App()
Expand Down Expand Up @@ -53,13 +60,19 @@ const app = new cdk.App()
passwordSecret: persistentResources.databasePasswordSecret,
},
securityGroups: securityGroupStack.securityGroups,
domains: {
hakijaDomain: `dev.${HAKIJA_DOMAIN}`,
hakijaDomainSv: `dev.${HAKIJA_DOMAIN_SV}`,
virkailijaDomain: `dev.${VIRKAILIJA_DOMAIN}`,
},
})
const dns = new DnsStack(dev, 'dns', {
hakijaDomain: `dev.${HAKIJA_DOMAIN}`,
hakijaDomainSv: `dev.${HAKIJA_DOMAIN_SV}`,
hakijaLegacyARecord: LEGACY_LOADBALANCER_IP,
virkailijaDomain: `dev.${VIRKAILIJA_DOMAIN}`,
databaseHostname: dbStack.clusterWriterEndpointHostname,
cloudfrontDistribution: vaService.cdnDistribution,

delegationRecord: {
env: 'prod',
Expand Down
15 changes: 11 additions & 4 deletions cdk/lib/security-group-stack.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as cdk from 'aws-cdk-lib'
import { Environment } from './va-env-stage'
import { Peer, Port, SecurityGroup, IVpc } from 'aws-cdk-lib/aws-ec2'
import { Peer, Port, SecurityGroup, IVpc, PrefixList } from 'aws-cdk-lib/aws-ec2'
import { HAKIJA_PORT, VIRKAILIJA_PORT } from './va-service-stack'

export interface VaSecurityGroups {
Expand Down Expand Up @@ -56,11 +56,19 @@ export class SecurityGroupStack extends cdk.Stack {
allowAllOutbound: true,
})

// Optimally we'd use AWS-managed prefix lists to allow CDN ingress only, but this is not yet properly supported
// https://github.com/aws/aws-cdk/issues/15115
this.securityGroups.albSecurityGroup.addIngressRule(
Peer.ipv4('62.165.154.10/32'),
Peer.anyIpv4(),
Port.tcp(80),
'Allow access from Reaktor office'
'Allow access from anywhere'
)
this.securityGroups.albSecurityGroup.addIngressRule(
Peer.anyIpv6(),
Port.tcp(80),
'Allow access from anywhere'
)

this.securityGroups.albSecurityGroup.addEgressRule(
this.securityGroups.vaServiceSecurityGroup,
Port.tcp(VIRKAILIJA_PORT),
Expand All @@ -71,7 +79,6 @@ export class SecurityGroupStack extends cdk.Stack {
Port.tcp(VIRKAILIJA_PORT),
'Allow access to virkailija from ALB'
)

this.securityGroups.albSecurityGroup.addEgressRule(
this.securityGroups.vaServiceSecurityGroup,
Port.tcp(HAKIJA_PORT),
Expand Down
114 changes: 69 additions & 45 deletions cdk/lib/va-service-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ import {
UlimitName,
} from 'aws-cdk-lib/aws-ecs'
import { Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'
import { DB_NAME as VA_DATABASE_NAME } from './db-stack'
import {
ApplicationListenerRule,
ApplicationLoadBalancer,
ApplicationProtocol,
ApplicationTargetGroup,
ListenerAction,
ListenerCondition,
XffHeaderProcessingMode,
} from 'aws-cdk-lib/aws-elasticloadbalancingv2'
import { Secret } from 'aws-cdk-lib/aws-secretsmanager'
Expand All @@ -34,9 +36,11 @@ import {
Distribution,
OriginAccessIdentity,
OriginRequestPolicy,
SSLMethod,
ViewerProtocolPolicy,
} from 'aws-cdk-lib/aws-cloudfront'
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins'
import { AWS_SERVICE_PREFIX } from '../bin/cdk'

const CONTAINER_NAME = 'valtionavustukset'
export const VIRKAILIJA_PORT = 8081 // = virkailija port
Expand All @@ -48,14 +52,23 @@ interface VaServiceStackProps extends cdk.StackProps {
db: DbProps
applicationLogGroup: LogGroup
securityGroups: VaSecurityGroups
domains: Domains
}

interface DbProps {
hostname: string
passwordSecret: Secret
}

interface Domains {
hakijaDomain: string
hakijaDomainSv: string
virkailijaDomain: string
}

export class VaServiceStack extends cdk.Stack {
cdnDistribution: Distribution

constructor(scope: Environment, id: string, props: VaServiceStackProps) {
super(scope, id, props)

Expand Down Expand Up @@ -155,49 +168,48 @@ export class VaServiceStack extends cdk.Stack {
healthCheckGracePeriod: Duration.minutes(10),
})

/* ---------- VIRKAILIJA LOAD BALANCER ---------- */
/* ---------- LOAD BALANCER ---------- */

const virkailijaTargetGroup = new ApplicationTargetGroup(this, 'va-virkailija-target-group', {
const loadBalancer = new ApplicationLoadBalancer(this, 'va-load-balancer', {
loadBalancerName: 'va-service',
securityGroup: albSecurityGroup,
xffHeaderProcessingMode: XffHeaderProcessingMode.APPEND,
internetFacing: true,
vpc: vpc,
preserveHostHeader: true,
})

const loadbalancerListener = loadBalancer.addListener('lb-http-listener', {
protocol: ApplicationProtocol.HTTP,
port: VIRKAILIJA_PORT,
targets: [
vaService.loadBalancerTarget({
containerName: CONTAINER_NAME,
containerPort: VIRKAILIJA_PORT,
}),
],
healthCheck: {
enabled: true,
interval: Duration.seconds(30),
path: '/api/healthcheck',
port: `${VIRKAILIJA_PORT}`,
},
port: 80,
open: true,
})

const virkailijaLoadBalancer = new ApplicationLoadBalancer(
const virkailijaTargetGroup = new ApplicationTargetGroup(
this,
'va-virkailija-load-balancer',
'va-virkailija-alb-target-group',
{
loadBalancerName: 'va-virkailija-service',
securityGroup: albSecurityGroup,
xffHeaderProcessingMode: XffHeaderProcessingMode.APPEND,
internetFacing: true,
vpc: vpc,
preserveHostHeader: true,
protocol: ApplicationProtocol.HTTP,
port: VIRKAILIJA_PORT,
targets: [
vaService.loadBalancerTarget({
containerName: CONTAINER_NAME,
containerPort: VIRKAILIJA_PORT,
}),
],
healthCheck: {
enabled: true,
interval: Duration.seconds(30),
path: '/api/healthcheck',
port: `${VIRKAILIJA_PORT}`,
},
}
)

const virkailijaListener = virkailijaLoadBalancer.addListener('virkailija-lb-http', {
protocol: ApplicationProtocol.HTTP,
port: 80,
defaultTargetGroups: [virkailijaTargetGroup],
open: false, // Allow only Reaktor office for now, app is not configured properly yet
})

/* ---------- HAKIJA LOAD BALANCER ---------- */

const hakijaTargetGroup = new ApplicationTargetGroup(this, 'va-hakija-target-group', {
const hakijaTargetGroup = new ApplicationTargetGroup(this, 'va-hakija-alb-target-group', {
vpc: vpc,
protocol: ApplicationProtocol.HTTP,
port: HAKIJA_PORT,
Expand All @@ -214,20 +226,23 @@ export class VaServiceStack extends cdk.Stack {
port: `${HAKIJA_PORT}`,
},
})
const hakijaLoadBalancer = new ApplicationLoadBalancer(this, 'va-hakija-load-balancer', {
loadBalancerName: 'va-hakija-service',
securityGroup: albSecurityGroup,
xffHeaderProcessingMode: XffHeaderProcessingMode.APPEND,
internetFacing: true,
vpc: vpc,
preserveHostHeader: true,

const { hakijaDomain, hakijaDomainSv, virkailijaDomain } = props.domains

/* ---------- VIRKAILIJA FQDN ---------- */
// aws.dev.virkailija.valtionavustukset.oph.fi
new ApplicationListenerRule(this, 'route-to-virkailija-from-host-headers', {
listener: loadbalancerListener,
priority: 10,
action: ListenerAction.forward([virkailijaTargetGroup]),
conditions: [ListenerCondition.hostHeaders([`${AWS_SERVICE_PREFIX}${virkailijaDomain}`])],
})

const hakijaListener = hakijaLoadBalancer.addListener('hakija-lb-http', {
protocol: ApplicationProtocol.HTTP,
port: 80,
defaultTargetGroups: [hakijaTargetGroup],
open: false, // Allow only Reaktor office for now, app is not configured properly yet
/* ---------- HAKIJA FQDN ---------- */
// aws.dev.valtionavustukset.oph.fi
// aws.dev.statsunderstod.oph.fi
loadbalancerListener.addAction('route-to-hakija-as-default', {
action: ListenerAction.forward([hakijaTargetGroup]),
})

/* ------------------------------ CDN -------------------------------- */
Expand All @@ -247,9 +262,17 @@ export class VaServiceStack extends cdk.Stack {
const oai = new OriginAccessIdentity(this, 'cdn-oai')
maintenancePageBucket.grantRead(oai)

const cdnDistribution = new Distribution(this, 'va-cdn', {
this.cdnDistribution = new Distribution(this, 'va-cdn', {
/*
domainNames: [
`${AWS_SERVICE_PREFIX}${hakijaDomain}`,
`${AWS_SERVICE_PREFIX}${hakijaDomainSv}`,
`${AWS_SERVICE_PREFIX}${virkailijaDomain}`,
],
sslSupportMethod: SSLMethod.SNI,
*/
defaultBehavior: {
origin: new origins.LoadBalancerV2Origin(virkailijaLoadBalancer),
origin: new origins.LoadBalancerV2Origin(loadBalancer),
allowedMethods: AllowedMethods.ALLOW_ALL,
originRequestPolicy: OriginRequestPolicy.ALL_VIEWER,
cachePolicy: CachePolicy.CACHING_DISABLED,
Expand All @@ -271,6 +294,7 @@ export class VaServiceStack extends cdk.Stack {
cachePolicy: CachePolicy.CACHING_DISABLED,
},
},
enableIpv6: false,
})
}
}

0 comments on commit 43a4190

Please sign in to comment.