Last active
February 27, 2024 12:13
-
-
Save andreialecu/df36776c0745641c6cad9737ba25474d to your computer and use it in GitHub Desktop.
aws-cdk terraform
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as cdk from "aws-cdk-lib"; | |
import { TerraformSupport } from "./terraform-support"; | |
import * as azureApp from "@cdk-cloudformation/tf-azuread-application"; | |
export class AzureApplicationStack extends cdk.Stack { | |
constructor(scope: cdk.App, id: string, props: cdk.StackProps) { | |
super(scope, id, props); | |
// First deploy step 1, then change to 2 and deploy again | |
let step = 1; | |
// Step 1, deploy this: | |
const terraform = new TerraformSupport(this, "TerraformConstruct", { | |
activateTypes: ["TF::AzureAD::Application"], | |
}); | |
if (step === 2) { | |
const app = new azureApp.CfnApplication(this, "AzureApplication", { | |
displayName: "Azure Test App", | |
signInAudience: "AzureADMultipleOrgs", | |
}); | |
new cdk.CfnOutput(this, "AzureAppId", { | |
value: app.attrApplicationId, | |
}); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Construct } from "constructs"; | |
import * as cdk from "aws-cdk-lib"; | |
import * as s3 from "aws-cdk-lib/aws-s3"; | |
import * as iam from "aws-cdk-lib/aws-iam"; | |
import * as lambda from "aws-cdk-lib/aws-lambda"; | |
import { aws_cloudformation as cloudformation } from "aws-cdk-lib"; | |
import fs = require("fs"); | |
export class TerraformSupport extends Construct { | |
executionRole: cdk.aws_iam.Role; | |
constructor( | |
scope: Construct, | |
id: string, | |
{ activateTypes }: { activateTypes: string[] } | |
) { | |
super(scope, id); | |
const stateS3Bucket = new s3.Bucket(this, "StateS3Bucket", { | |
bucketName: `cfntf-${cdk.Stack.of(this).region}-${ | |
cdk.Stack.of(this).account | |
}`, | |
encryption: s3.BucketEncryption.S3_MANAGED, | |
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, | |
removalPolicy: cdk.RemovalPolicy.DESTROY, | |
autoDeleteObjects: true, | |
}); | |
const executorLambdaServiceRole = new iam.Role( | |
this, | |
"ExecutorLambdaServiceRole", | |
{ | |
assumedBy: new iam.ServicePrincipal("lambda.amazonaws.com"), | |
inlinePolicies: { | |
CoreFunctionality: new iam.PolicyDocument({ | |
statements: [ | |
new iam.PolicyStatement({ | |
actions: [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents", | |
], | |
resources: ["*"], | |
}), | |
new iam.PolicyStatement({ | |
actions: ["secretsmanager:GetSecretValue"], | |
resources: [ | |
cdk.Arn.format( | |
{ | |
service: "secretsmanager", | |
resource: "secret", | |
arnFormat: cdk.ArnFormat.COLON_RESOURCE_NAME, | |
resourceName: "terraform/*", | |
}, | |
cdk.Stack.of(this) | |
), | |
], | |
}), | |
new iam.PolicyStatement({ | |
actions: ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"], | |
resources: [stateS3Bucket.arnForObjects("*")], | |
}), | |
], | |
}), | |
}, | |
} | |
); | |
const executorLambdaFunction = new lambda.Function( | |
this, | |
"ExecutorLambdaFunction", | |
{ | |
functionName: "cfntf-executor", | |
code: lambda.Code.fromAsset( | |
// fromAsset requires a directory, so we create a temporary one | |
fs.mkdtempSync("cdktfsupp"), | |
{ | |
assetHashType: cdk.AssetHashType.CUSTOM, | |
assetHash: "v1.1-tf-1.7.4", | |
bundling: { | |
image: lambda.Runtime.PYTHON_3_8.bundlingImage, | |
command: [ | |
"bash", | |
"-c", | |
[ | |
"curl -o /asset-output/terraform.zip https://releases.hashicorp.com/terraform/1.7.4/terraform_1.7.4_linux_arm64.zip", | |
"unzip -o /asset-output/terraform.zip -d /asset-output", | |
"rm /asset-output/terraform.zip", | |
"curl -o /asset-output/index.py https://raw.githubusercontent.com/iann0036/cfn-tf-custom-types/755fbfc7eb6f30f3d7dfca700bad00ba19ee7ee3/executor_lambda/index.py", | |
"ls -la /asset-output", | |
].join(" && "), | |
], | |
}, | |
} | |
), | |
handler: "index.handler", | |
runtime: lambda.Runtime.PYTHON_3_8, | |
architecture: lambda.Architecture.ARM_64, | |
role: executorLambdaServiceRole, | |
environment: { | |
BUCKET: stateS3Bucket.bucketName, | |
}, | |
memorySize: 1024, | |
timeout: cdk.Duration.minutes(15), | |
retryAttempts: 1, | |
logRetention: cdk.aws_logs.RetentionDays.TWO_WEEKS, | |
} | |
); | |
this.executionRole = new iam.Role(this, "ExecutionRole", { | |
assumedBy: new iam.ServicePrincipal( | |
"resources.cloudformation.amazonaws.com" | |
), | |
}); | |
this.executionRole.addToPolicy( | |
new iam.PolicyStatement({ | |
actions: ["lambda:InvokeFunction"], | |
resources: [executorLambdaFunction.functionArn], | |
}) | |
); | |
this.executionRole.addToPolicy( | |
new iam.PolicyStatement({ | |
actions: ["s3:DeleteObject", "s3:GetObject", "s3:ListBucket"], | |
resources: [stateS3Bucket.arnForObjects("*")], | |
}) | |
); | |
activateTypes.forEach((typeName) => { | |
const cfnTypeActivation = new cloudformation.CfnTypeActivation( | |
this, | |
"CfActivate_" + typeName.replace("::", ""), | |
{ | |
autoUpdate: true, | |
publisherId: "e1238fdd31aee1839e14fb3fb2dac9db154dae29", | |
type: "RESOURCE", | |
typeName, | |
executionRoleArn: this.executionRole.roleArn, | |
} | |
); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage:
Deployment will need to be done in two steps, because we first need to activate the
TF::*
CloudFormation extension that we need to use.See the
step
variable and logic inazure-app.stack.ts
You will then need to create a
terraform/azuread
secret. You can use this as a template:Note that you may need to grant the following permissions to the service principal, as per:
https://github.com/iann0036/cfn-tf-custom-types/blob/docs/resources/azuread/TF-AzureAD-Application/docs/README.md
You can do that via the CLI using these commands (you can read what the identifiers represent here):
Afterwards, set
step=2
, deploy again, and you should see a new Azure application in your account.