Skip to content

Commit 4b5ffc8

Browse files
authored
added RDS IAM Auth example (#908)
* added RDS IAM Auth example * restructuring project for testing * removing CDK temp files * removing package-lock.json
1 parent 4ee10b0 commit 4b5ffc8

File tree

10 files changed

+3473
-0
lines changed

10 files changed

+3473
-0
lines changed
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Rust
2+
debug/
3+
target/
4+
5+
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
6+
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
7+
Cargo.lock
8+
9+
# These are backup files generated by rustfmt
10+
**/*.rs.bk
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "rds-iam-rust-lambda"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
lambda_runtime = { path = "../../lambda-runtime" }
8+
serde_json = "1.0.120"
9+
aws-config = "1.0.1"
10+
aws-credential-types = "1.0.1"
11+
aws-sigv4 = "1.0.1"
12+
url = "2.5.0"
13+
tokio = { version = "1.25.0", features = ["full"] }
14+
sqlx = { version = "0.7.4", features = ["tls-rustls", "postgres", "runtime-tokio"] }
+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# CDK
2+
node_modules
3+
cdk.json
4+
5+
# Logs
6+
logs
7+
*.log
8+
npm-debug.log*
9+
yarn-debug.log*
10+
yarn-error.log*
11+
lerna-debug.log*
12+
.pnpm-debug.log*
13+
14+
# Diagnostic reports (https://nodejs.org/api/report.html)
15+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
16+
17+
# Runtime data
18+
pids
19+
*.pid
20+
*.seed
21+
*.pid.lock
22+
23+
# Directory for instrumented libs generated by jscoverage/JSCover
24+
lib-cov
25+
26+
# Coverage directory used by tools like istanbul
27+
coverage
28+
*.lcov
29+
30+
# nyc test coverage
31+
.nyc_output
32+
33+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
34+
.grunt
35+
36+
# Bower dependency directory (https://bower.io/)
37+
bower_components
38+
39+
# node-waf configuration
40+
.lock-wscript
41+
42+
# Compiled binary addons (https://nodejs.org/api/addons.html)
43+
build/Release
44+
45+
# Dependency directories
46+
node_modules/
47+
jspm_packages/
48+
49+
# Snowpack dependency directory (https://snowpack.dev/)
50+
web_modules/
51+
52+
# TypeScript cache
53+
*.tsbuildinfo
54+
55+
# Optional npm cache directory
56+
.npm
57+
58+
# Optional eslint cache
59+
.eslintcache
60+
61+
# Optional stylelint cache
62+
.stylelintcache
63+
64+
# Microbundle cache
65+
.rpt2_cache/
66+
.rts2_cache_cjs/
67+
.rts2_cache_es/
68+
.rts2_cache_umd/
69+
70+
# Optional REPL history
71+
.node_repl_history
72+
73+
# Output of 'npm pack'
74+
*.tgz
75+
76+
# Yarn Integrity file
77+
.yarn-integrity
78+
79+
# dotenv environment variable files
80+
.env
81+
.env.development.local
82+
.env.test.local
83+
.env.production.local
84+
.env.local
85+
86+
# parcel-bundler cache (https://parceljs.org/)
87+
.cache
88+
.parcel-cache
89+
90+
# Next.js build output
91+
.next
92+
out
93+
94+
# Nuxt.js build / generate output
95+
.nuxt
96+
dist
97+
98+
# Gatsby files
99+
.cache/
100+
# Comment in the public line in if your project uses Gatsby and not Next.js
101+
# https://nextjs.org/blog/next-9-1#public-directory-support
102+
# public
103+
104+
# vuepress build output
105+
.vuepress/dist
106+
107+
# vuepress v2.x temp and cache directory
108+
.temp
109+
.cache
110+
111+
# Docusaurus cache and generated files
112+
.docusaurus
113+
114+
# Serverless directories
115+
.serverless/
116+
117+
# FuseBox cache
118+
.fusebox/
119+
120+
# DynamoDB Local files
121+
.dynamodb/
122+
123+
# TernJS port file
124+
.tern-port
125+
126+
# Stores VSCode versions used for testing VSCode extensions
127+
.vscode-test
128+
129+
# yarn v2
130+
.yarn/cache
131+
.yarn/unplugged
132+
.yarn/build-state.yml
133+
.yarn/install-state.gz
134+
.pnp.*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# AWS Lambda Function that uses RDS's IAM Authnetication
2+
This example shows how to build and deploy Rust Lambda Function and an RDS instance using AWS CDK and
3+
4+
Build & Deploy
5+
1. `npm install`
6+
1. `npx cdk deploy`
7+
1. Using the dev instance or using a local Postgres client: connect into the RDS instance as root and create the required Users with permissions `CREATE USER lambda; GRANT rds_iam TO lambda;`
8+
1. Go to the Lambda Function in the AWS console and invoke the lambda function
+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { join } from 'path';
2+
import * as cdk from 'aws-cdk-lib';
3+
import * as rds from 'aws-cdk-lib/aws-rds';
4+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
5+
import * as lambda from 'aws-cdk-lib/aws-lambda';
6+
import { RustFunction } from '@cdklabs/aws-lambda-rust'
7+
8+
class LambdaRDSStack extends cdk.Stack {
9+
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
10+
super(scope, id, props);
11+
12+
// Create a VPC
13+
const vpc = new ec2.Vpc(this, 'VPC');
14+
15+
// Admin DB user
16+
const DB_ADMIN_USERNAME = 'root';
17+
const DB_USERNAME = 'lambda';
18+
19+
// Lambda DB user
20+
const DB_NAME = 'foo';
21+
22+
// Create an RDS instance
23+
const db = new rds.DatabaseInstance(this, 'Postgres', {
24+
engine: rds.DatabaseInstanceEngine.POSTGRES,
25+
vpc,
26+
vpcSubnets: vpc.selectSubnets({ subnetType: ec2.SubnetType.PUBLIC }),
27+
credentials: rds.Credentials.fromGeneratedSecret(DB_ADMIN_USERNAME),
28+
iamAuthentication: true,
29+
publiclyAccessible: true,
30+
databaseName: DB_NAME,
31+
deleteAutomatedBackups: true,
32+
removalPolicy: cdk.RemovalPolicy.DESTROY
33+
})
34+
35+
db.connections.allowFromAnyIpv4(ec2.Port.allTcp())
36+
37+
// RDS SSL Cert Lambda Layer alternative to loading the certificates at compile time
38+
/*
39+
const certLayer = new lambda.LayerVersion(this, 'CertLayer', {
40+
description: 'SSL Certificate Layer',
41+
code: lambda.Code.fromAsset('certs'),
42+
compatibleArchitectures: [lambda.Architecture.X86_64, lambda.Architecture.ARM_64]
43+
});
44+
*/
45+
46+
const lambdaSG = new ec2.SecurityGroup(this, 'LambdaSG', {
47+
securityGroupName: 'LambdaSG',
48+
allowAllOutbound: true,
49+
vpc: vpc,
50+
})
51+
// create a rust lambda function
52+
const rustLambdaFunction = new RustFunction(this, "lambda", {
53+
entry: join(__dirname, '..', 'lambda'),
54+
vpc: vpc,
55+
securityGroups: [lambdaSG],
56+
environment: {
57+
DB_HOSTNAME: db.dbInstanceEndpointAddress,
58+
DB_PORT: db.dbInstanceEndpointPort,
59+
DB_NAME: DB_NAME,
60+
DB_USERNAME: DB_USERNAME,
61+
},
62+
bundling: {
63+
forceDockerBundling: true,
64+
},
65+
runtime: lambda.Runtime.PROVIDED_AL2023,
66+
timeout: cdk.Duration.seconds(60),
67+
});
68+
69+
// MySQL
70+
/*
71+
CREATE USER 'lambda' IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS';
72+
GRANT ALL PRIVILEGES ON foo.* TO 'lambda';
73+
ALTER USER 'lambda' REQUIRE SSL;
74+
*/
75+
76+
// Postgres
77+
/*
78+
CREATE USER db_userx;
79+
GRANT rds_iam TO db_userx;
80+
*/
81+
db.grantConnect(rustLambdaFunction, DB_USERNAME);
82+
db.connections.allowDefaultPortFrom(rustLambdaFunction);
83+
84+
/*
85+
Dev Instance for initialising the datbase with the above commands
86+
*/
87+
const devInstance = new ec2.Instance(this, 'dev', {
88+
vpc,
89+
vpcSubnets: vpc.selectSubnets({ subnetType: ec2.SubnetType.PUBLIC }),
90+
machineImage: ec2.MachineImage.latestAmazonLinux2023(),
91+
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MEDIUM)
92+
})
93+
db.grantConnect(devInstance, DB_ADMIN_USERNAME);
94+
db.grantConnect(devInstance, DB_USERNAME);
95+
db.connections.allowDefaultPortFrom(devInstance);
96+
97+
// Output the Lambda function ARN
98+
new cdk.CfnOutput(this, 'LambdaFunctionConsole', {
99+
value: `https://${this.region}.console.aws.amazon.com/lambda/home?region=${this.region}#/functions/${rustLambdaFunction.functionName}?tab=testing`
100+
});
101+
}
102+
}
103+
104+
const app = new cdk.App();
105+
new LambdaRDSStack(app, 'LambdaRDSStack');
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"app": "npx ts-node --prefer-ts-exts app.ts",
3+
"watch": {
4+
"include": [
5+
"**.js",
6+
"**.rs",
7+
"**.ts"
8+
],
9+
"exclude": [
10+
"README.md",
11+
"cdk*.json",
12+
"**/*.d.ts",
13+
"**/*.js",
14+
"tsconfig.json",
15+
"package*.json",
16+
"yarn.lock",
17+
"node_modules",
18+
"test"
19+
]
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"dependencies": {
3+
"@cdklabs/aws-lambda-rust": "0.0.4",
4+
"aws-cdk-lib": "^2.147.0",
5+
"path": "^0.12.7",
6+
"prettier": "^3.3.2",
7+
"rust.aws-cdk-lambda": "^1.2.1",
8+
"ts-node": "^10.9.2"
9+
},
10+
"devDependencies": {
11+
"@types/node": "^20.14.10"
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"module": "commonjs",
5+
"lib": [
6+
"es2020",
7+
"dom"
8+
],
9+
"declaration": true,
10+
"strict": true,
11+
"noImplicitAny": true,
12+
"strictNullChecks": true,
13+
"noImplicitThis": true,
14+
"alwaysStrict": true,
15+
"noUnusedLocals": false,
16+
"noUnusedParameters": false,
17+
"noImplicitReturns": true,
18+
"noFallthroughCasesInSwitch": false,
19+
"inlineSourceMap": true,
20+
"inlineSources": true,
21+
"experimentalDecorators": true,
22+
"strictPropertyInitialization": false,
23+
"typeRoots": [
24+
"./node_modules/@types"
25+
]
26+
},
27+
"exclude": [
28+
"node_modules",
29+
"cdk.out"
30+
]
31+
}

0 commit comments

Comments
 (0)