Conditional IF statement in cloudformation to create Encrypted EBS either with default KMS or user managed KMS

0

Hi Team, Need help. I am trying to create a CFT to spin up ec2 instances where I would like to make sure EBS is encrypted with default KMS key unless a key arn is provided in the parameter. I was trying the below code but I am sure I am missing the logic, could you please have a look and help me if you can please? This code is failing after launch since condition is not matching while passing no KMS key arn with in the parameter section then default key supposed to be taken in.

AWSTemplateFormatVersion: '2010-09-09'
Description: Create an EC2 instance with EBS encryption using a custom or default KMS key

Parameters:
  KeyName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance

  InstanceType:
    Type: String
    Default: t2.micro
    Description: EC2 instance type

  ImageId:
    Type: AWS::EC2::Image::Id
    Default: ami-0c94755bb95c71c99
    Description: AMI ID for the EC2 instance

  CustomKMSKeyArn:
    Type: String
    Default: ''
    Description: (Optional) ARN of a custom KMS key to use for EBS encryption

Resources:
  IAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEC2FullAccess
        - arn:aws:iam::aws:policy/AWSKeyManagementServicePowerUser

  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      KeyName: !Ref KeyName
      IamInstanceProfile: !Ref IAMRole
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: 20
            Encrypted: true
            KmsKeyId: !If
              - UseCustomKMSKey
              - !Ref CustomKMSKeyArn
              - !Ref 'AWS::Region'

Conditions:
  UseCustomKMSKey: !Not [!Equals [!Ref CustomKMSKeyArn, '']]

Outputs:
  InstanceId:
    Description: The ID of the EC2 instance
    Value: !Ref EC2Instance
    Export:
      Name: ec2-instance-id
asked 4 months ago145 views
1 Answer
2

Hello,

You can use the AWS::NoValue parameter when you want to encrypt the EBS using a custom CustomKMSKeyArn if it's provided as an input parameter. If the condition evaluates to false, CloudFormation removes the KmsKeyId property and encrypted using default EBS Kms key.

I also found one more issue with CF template, You need to create an InstanceProfile resource to attach the IAM Role to the EC2 instance.

AWSTemplateFormatVersion: '2010-09-09'
Description: Create an EC2 instance with EBS encryption using a custom or default KMS key

Parameters:
  KeyName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance

  InstanceType:
    Type: String
    Default: t2.micro
    Description: EC2 instance type

  ImageId:
    Type: AWS::EC2::Image::Id
    Default: ami-0c94755bb95c71c99
    Description: AMI ID for the EC2 instance

  CustomKMSKeyArn:
    Type: String
    Default: ''
    Description: (Optional) ARN of a custom KMS key to use for EBS encryption

Conditions:
  UseCustomKMSKey: !Not [!Equals [!Ref CustomKMSKeyArn, '']]

Resources:
  IAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEC2FullAccess
        - arn:aws:iam::aws:policy/AWSKeyManagementServicePowerUser

  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref IAMRole

  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      KeyName: !Ref KeyName
      IamInstanceProfile: !Ref InstanceProfile
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: 20
            Encrypted: true
            KmsKeyId: !If
              - UseCustomKMSKey
              - !Ref CustomKMSKeyArn
              - !Ref 'AWS::NoValue'

Outputs:
  InstanceId:
    Description: The ID of the EC2 instance
    Value: !Ref EC2Instance
    Export:
      Name: ec2-instance-id
profile picture
EXPERT
answered 4 months ago
profile picture
EXPERT
reviewed 4 months ago
profile picture
EXPERT
reviewed 4 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions