Skip to content

Commit

Permalink
allow for import of rds instances and proxies (#279)
Browse files Browse the repository at this point in the history
  • Loading branch information
jhsinger-klotho authored Feb 22, 2023
1 parent 7876292 commit 80df957
Show file tree
Hide file tree
Showing 7 changed files with 255 additions and 186 deletions.
170 changes: 1 addition & 169 deletions pkg/infra/pulumi_aws/deploylib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export interface TopologyEdgeData {
target: string
}

export const kloConfig = new pulumi.Config('klo')
export const kloConfig: pulumi.Config = new pulumi.Config('klo')

export class CloudCCLib {
secrets = new Map<string, aws.secretsmanager.Secret>()
Expand Down Expand Up @@ -1003,174 +1003,6 @@ export class CloudCCLib {
)
}

public setupRDS(orm: string, args: Partial<aws.rds.InstanceArgs>) {
if (!this.subnetGroup) {
const subnetGroupName = sanitized(AwsSanitizer.RDS.dbSubnetGroup.nameValidation())`${h(
this.name
)}`
this.subnetGroup = new aws.rds.SubnetGroup(subnetGroupName, {
subnetIds: this.privateSubnetIds,
tags: {
Name: 'Klotho DB subnet group',
},
})
}

const dbName = sanitized(
AwsSanitizer.RDS.engine.pg.database.nameValidation()
)`${orm.toLowerCase()}`
const config = new pulumi.Config()
const username = config.require(`${dbName}_username`)
const password = config.requireSecret(`${dbName}_password`)

// create the db resources
validate(dbName, AwsSanitizer.RDS.instance.nameValidation())
const rds = new aws.rds.Instance(
dbName,
{
instanceClass: 'db.t4g.micro',
...args,
engine: 'postgres',
dbName: dbName,
username: username,
password: password,
iamDatabaseAuthenticationEnabled: true,
dbSubnetGroupName: this.subnetGroup.name,
vpcSecurityGroupIds: this.sgs,
},
{ protect: this.protect }
)

// setup secrets for the proxy
const secretName = `${dbName}_secret`
const ssmSecretName = `${this.name}-${secretName}`
validate(ssmSecretName, AwsSanitizer.SecretsManager.secret.nameValidation())
let rdsSecret = new aws.secretsmanager.Secret(`${secretName}`, {
name: ssmSecretName,
recoveryWindowInDays: 0,
})

const rdsSecretValues = {
username: username,
password: password,
engine: 'postgres',
host: rds.address,
port: rds.port,
dbname: dbName,
dbInstanceIdentifier: rds.id,
iamDatabaseAuthenticationEnabled: false,
}

const secret = new aws.secretsmanager.SecretVersion(`${secretName}`, {
secretId: rdsSecret.id,
secretString: pulumi.output(rdsSecretValues).apply((v) => JSON.stringify(v)),
})

this.topology.topologyIconData.forEach((resource) => {
if (resource.kind == Resource.secret) {
this.topology.topologyEdgeData.forEach((edge) => {
if (edge.target == resource.id) {
this.addPolicyStatementForName(
this.resourceIdToResource.get(edge.source).title,
{
Effect: 'Allow',
Action: ['secretsmanager:GetSecretValue'],
Resource: [secret.arn],
}
)
}
})
}
})

// prettier-ignore
const ormRoleName = sanitized(AwsSanitizer.IAM.role.nameValidation())`${h(dbName)}-ormsecretrole`
//setup role for proxy
const role = new aws.iam.Role(ormRoleName, {
assumeRolePolicy: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: {
Service: 'rds.amazonaws.com',
},
Action: 'sts:AssumeRole',
},
],
},
})

// prettier-ignore
const ormPolicyName = sanitized(AwsSanitizer.IAM.policy.nameValidation())`${h(dbName)}-ormsecretpolicy`
const policy = new aws.iam.Policy(ormPolicyName, {
description: 'klotho orm secret policy',
policy: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: 'secretsmanager:GetSecretValue',
Resource: [secret.arn],
},
],
},
})

const attach = new aws.iam.RolePolicyAttachment(`${dbName}-ormattach`, {
role: role.name,
policyArn: policy.arn,
})

// setup the rds proxy
const proxyName = sanitized(AwsSanitizer.RDS.dbProxy.nameValidation())`${h(dbName)}`
const proxy = new aws.rds.Proxy(proxyName, {
debugLogging: false,
engineFamily: 'POSTGRESQL',
idleClientTimeout: 1800,
requireTls: false,
roleArn: role.arn,
vpcSecurityGroupIds: this.sgs,
vpcSubnetIds: this.privateSubnetIds,
auths: [
{
authScheme: 'SECRETS',
description: 'use the secrets generated by klotho',
iamAuth: 'DISABLED',
secretArn: secret.arn,
},
],
})

const proxyDefaultTargetGroup = new aws.rds.ProxyDefaultTargetGroup(`${dbName}`, {
dbProxyName: proxy.name,
connectionPoolConfig: {
connectionBorrowTimeout: 120,
maxConnectionsPercent: 100,
maxIdleConnectionsPercent: 50,
},
})
const proxyTarget = new aws.rds.ProxyTarget(`${dbName}`, {
dbInstanceIdentifier: rds.id,
dbProxyName: proxy.name,
targetGroupName: proxyDefaultTargetGroup.name,
})

const clients = this.addConnectionString(
orm,
pulumi.interpolate`postgresql://${username}:${password}@${proxy.endpoint}:5432/${dbName}`
)

const resource = pulumi.interpolate`arn:aws:rds-db:${this.region}:${this.account.accountId}:dbuser:${rds.resourceId}/${username}`
for (const client of clients) {
this.addPolicyStatementForName(this.resourceIdToResource.get(client).title, {
Effect: 'Allow',
Action: ['rds-db:connect'],
Resource: resource,
})
}
}

public addConnectionString(orm: string, connectionString: pulumi.Output<string>) {
const clients: string[] = []
this.topology.topologyIconData.forEach((resource) => {
Expand Down
Loading

0 comments on commit 80df957

Please sign in to comment.