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 hidden or 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 hidden or 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
stepvariable and logic inazure-app.stack.tsYou will then need to create a
terraform/azureadsecret. 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):
az ad app permission add --id {appId} --api 00000003-0000-0000-c000-000000000000 --api-permissions df021288-bdef-4463-88db-98f22de89214=Role 1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9=Role az ad app permission grant --id {appId} --api 00000003-0000-0000-c000-00000000000Afterwards, set
step=2, deploy again, and you should see a new Azure application in your account.