Day 016 - 100DaysAWSIaCDevopsChallenge
In my previous post,
The infrastructure consists of the following components:
VPCand two (02)Subnets(private and public subnet) to manage network traffic within the server and database instance.
Internet Gatewayto allow internet communication between our secured cloud environment and external networks.
Security groupto control access to the server and database based on IP addresses and ports connections.
EC2 Instanceto host the SonarQube server (including the Web Server, ElasticSearch, and Postgres Database).
Key Pairthe private key that allows external hosts to connect securely to the instance.
Secret Managerto securely store the database user password.
IAM Roleto allow EC2 Instance to connect to Secret Manager and retrieve database password
Elastic IP (EIP)- The static IP to attach to the EC2 Instance. It allows to maintain a fixed IP address aven if the instance is stopped of restarted.
Nat Gatewayto allow instance (here database instance) in a private subnet to connect to the internet or other AWS Service without exposing then to internet traffic.
RDS PostgreSQLthe database instance to host the sonarqube data.
Create the database Construct
interface DatabaseProps extends CustomProps {
vpc: IVpc,
sg?: ISecurityGroup // the security group for SonarQube Server Instance
}
export class Database extends Construct {
private readonly _dbInstanceArn: string
private readonly _passwordSecretArn: string
private readonly _instanceEndpointUrl: string
constructor(scope: Construct, id: string, props: DatabaseProps) {
super(scope, id)
const secret: ISecret = new aws_secretsmanager.Secret(this, 'SecretResource', {
secretName: 'database-instance-secret',
generateSecretString: {
secretStringTemplate: JSON.stringify({ username: props.databaseUsername }),
generateStringKey: 'password',
excludeCharacters: '/@"`()[]\'',
includeSpace: false
}
})
const securityGroup = new SecurityGroup(this, 'DatabaseSecurityGroupeResource', {
securityGroupName: 'sq-database-sg',
disableInlineRules: false,
allowAllOutbound: true,
vpc: props.vpc,
description: 'Database instance security group'
})
securityGroup.addIngressRule(
Peer.securityGroupId(props.sg!.securityGroupId),
Port.tcp(props.databasePort ?? 5432), 'Allow EC2 to connect to the database instance')
const db = new rds.DatabaseInstance(this, 'DatabaseInstanceResource', {
engine: rds.DatabaseInstanceEngine.postgres({
version: rds.PostgresEngineVersion.VER_12_16
}),
vpc: props.vpc,
networkType: rds.NetworkType.IPV4,
vpcSubnets: props.vpc.selectSubnets({ subnetType: SubnetType.PRIVATE_WITH_EGRESS }),
instanceType: InstanceType.of(InstanceClass.BURSTABLE3, InstanceSize.MICRO),
publiclyAccessible: false,
storageType: StorageType.GP3,
credentials: rds.Credentials.fromSecret(secret, props.databaseUsername),
allocatedStorage: 20,
databaseName: props.databaseName,
instanceIdentifier: 'sonarqube-db-1',
port: props.databasePort ?? 5432,
securityGroups: [
securityGroup
]
})
this._dbInstanceArn = db.instanceArn
this._passwordSecretArn = secret.secretArn
this._instanceEndpointUrl = db.instanceEndpoint.socketAddress
}
get dbInstanceArn(): string {
return this._dbInstanceArn
}
get passwordSecretArn() {
return this._passwordSecretArn
}
get instanceEndpointUrl(): string {
return this._instanceEndpointUrl
}
}
The important thing to know here is the snippet code:
securityGroup.addIngressRule(
Peer.securityGroupId(props.sg!.securityGroupId),
Port.tcp(props.databasePort ?? 5432), 'Allow EC2 to connect to the database instance')
This code allows communication between the database and the EC2 instance server through the specified port.
Update the Stack
This is the update for the stack created in the previous article
SOCIAL SHARE CARD GENERATOR