Create IAM User credentails in a secure way by AWS CDK with Deno.
Bootstrap a CDK using Deno.
# Bootstrap a CDK using Deno
# Run in a empty directory
alias cdk="deno run -A npm:aws-cdk"
export AWS_REGION=ap-northeast-1
cat << EOF > cdk.json
{
"app": "deno run -A https://raw.githubusercontent.com/jlandowner/deno-cdk-iam-creds/main/cdk.ts"
}
EOF
cdk bootstrap
Create a IAM User and generate access key.
(remove -A
option for a secure execution)
# Create a default IAM User and generate access key.
cdk deploy
# Retreive the secerts from Secrets Manager.
deno run -A https://raw.githubusercontent.com/jlandowner/deno-cdk-iam-creds/main/mod.ts
The output like this.
{
"AWS_ACCESS_KEY_ID": "xxxxxxxxxxxxxxx",
"AWS_SECRET_ACCESS_KEY": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
After you get the credentails, you should disable the secret by disableSecret
context.
# Delete the secrets in Secrets Manager.
cdk deploy --context disableSecret=1
# After disabled, you cannot get the secerts.
deno run -A https://raw.githubusercontent.com/jlandowner/deno-cdk-iam-creds/main/mod.ts
Also, you can create the secret again by just deploying again.
# Create the secret again
cdk deploy
To clean up the user, just destroy the cdk app.
# Cleen up
cdk destroy
You can use your own app. Here's an example.
import cdk from "npm:aws-cdk-lib";
import { cdkIAMCredentialSecret } from "https://raw.githubusercontent.com/jlandowner/deno-cdk-iam-creds/main/mod.ts";
class IAMUserStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// create IAM User
const user = new cdk.aws_iam.User(this, "User");
// You can create inline policies or attach managed policies to the user like this.
const policy = new cdk.aws_iam.Policy(this, "Policy", {
statements: [
new cdk.aws_iam.PolicyStatement({
actions: ["dynamodb:*"],
resources: ["arn:aws:dynamodb:*:*:table/MyTable"],
effect: cdk.aws_iam.Effect.ALLOW,
}),
],
});
policy.attachToUser(user);
// generate the IAM User's access key in Secrets Manager.
cdkIAMCredentialSecret(this, user);
}
}
const app = new cdk.App();
new IAMUserStack(app, "IAMUserStack", {
stackName: app.node.tryGetContext("stackName"),
env: {
account: Deno.env.get("CDK_DEFAULT_ACCOUNT"),
region: Deno.env.get("CDK_DEFAULT_REGION")
}
});
app.synth();
Save as yourapp.ts
. Then, update cdk.json
and deploy the cdk app.
{
"app": "deno run -A yourapp.ts"
}
You can retrive the secret value not only JSON stdout but also in your program.
For example, save it as a Kubernetes Secret, Base64-encoded and environment variable formatted.
import { encodeBase64 } from "https://deno.land/std@0.215.0/encoding/base64.ts";
import { stringify } from "https://deno.land/std@0.215.0/yaml/mod.ts";
import { getIAMCredentialSecretByStack } from "https://raw.githubusercontent.com/jlandowner/deno-cdk-iam-creds/main/mod.ts";
const secret = await getIAMCredentialSecretByStack("IAMUserStack");
Deno.writeTextFileSync("secret.yaml", stringify({
apiVersion: "v1",
kind: "Secret",
metadata: {
name: "aws-credentials-secret",
},
data: {
AWS_ACCESS_KEY_ID: encodeBase64(secret.AWS_ACCESS_KEY_ID),
AWS_SECRET_ACCESS_KEY: encodeBase64(secret.AWS_SECRET_ACCESS_KEY),
},
}));