1
votes

How can I trigger a Lambda function using AWS CDK after an RDS instance is up?

I am setting up a system with an RDS instance and an EKS cluster using AWS CDK and Typescript. After the RDS instance is created, I would like to set up some users in the database instance to be used by microservices on EKS.

I created a Custom Resource backed by a Lambda function for this, also implemented in Typescript. The lambda function retrieves the secret generated by CDK for the RDS instance plus some secrets for my database users, connects to the database and creates the database users. Ideally, the custom resource runs after the database instance is up and before the microservices are installed. How can I achieve this?

I haven't found a way to explicitly declare the dependency and my Lambda does not technically require a dependency (other than using secret.grantRead(lambda)). Just running a retry loop in Lambda until everything is up will likely not work thanks to the long creation times. Any code snippets/examples/... greatly appreciated, I have only found references about the general approach so far.

Update with details in reply to @jogold: With

    const database = new rds.DatabaseInstance(this, 'db', {
      instanceIdentifier: conf.systemName,
      engine: rds.DatabaseInstanceEngine.POSTGRES,
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MICRO),
      masterUsername: MASTER_USER,
      allocatedStorage: 20, maxAllocatedStorage: 100,
      multiAz: conf.isProduction,
      storageEncrypted: true,
      backupRetention: cdk.Duration.days(7),
      deletionProtection: false, 
      vpc, securityGroups: [ rdsSG ]
    });

CDK will generate a secret with some more or less random name with the access credentials to the database. I tried attaching the secret directly to my Lambda:

    new cdk.CustomResource(this, 'preinstall', { 
      serviceToken: preinstallProvider.serviceToken,
      properties: { secret: database.secret }
    });

But that gives me

    Error: Resolution error: Resolution error: Trying to resolve() a Construct at /Resources/${Token[td000.preinstall.Default.LogicalID.221]}/Properties/dbSecret/node/_actualNode.

Also, it looks like the interface ISecret doesn't have the ID/name of the secret, so I wouldn't know what to do with it in the Lambda.

1
What do you mean that there is no " way to explicitly declare the dependency" between RDS and your CR? If you don't want to use DependsOn (or CDK equivalent), then any reference in your CR to RDS resource (e.g. rds name) would create a dependency.Marcin
On which secret is your Lambda function relying? It should reference the "attached" secret. Can you share some code?jogold
@Marcin I think that's the catch ... I don't know what the CDK equivalent of "DependsOn" is. I have searched the CDK docs for it, but couldn't find anything. I am adding permission to the secret, not sure if that counts as dependency.André
@jogold I am querying the secrets with listSecrets in the Lambda function. I haven't found a way to attach the secrets. I can use describeSecret() or getSecretValue() only with the secret ID/name. However, if I let the AWS SDK create the RDS instance without providing a hardcoded password, I am not getting the secret ID returned.André

1 Answers

2
votes

CDK will usually try to guess the dependencies for you and ensure that they're created in the correct order. Where this doesn't work (as in your example), you can explicity declare that one resource depends on another. For example:

const customResource = new cdk.CustomResource(this, 'preinstall', { 
  serviceToken: preinstallProvider.serviceToken,
  properties: { secret: database.secret }
});

customResource.node.addDependency(database);

See the docs for more details https://docs.aws.amazon.com/cdk/api/latest/docs/core-readme.html#construct-dependencies