全リージョンのEBSデフォルト暗号化をLambda(Python3)から有効化する

2022.03.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

タイトルの通りですが、Lambdaから全リージョンのEBSデフォルト暗号化を有効化したのでサンプルとしてコードを置いておきます。ご自由にお使いください。

CloudFormationのLambda-backed custom resourcesを使ったパターンは以下のブログで紹介されていますので、用途によって使い分けください。

[小ネタ]Lambda-backed custom resourcesでEBSデフォルト暗号化のアカウント設定を有効にする | DevelopersIO

サンプルコード

先にLambdaで利用するコードを載せておきます。LambdaのランタイムはPython3.8で動作確認をしています。

ログの出力や有効後のリソースチェックはしていますが、あくまでサンプルとしてご利用ください。

EBSデフォルト暗号化を全リージョン有効化する

import boto3
import logging
from typing import List

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def describe_regions() -> list:
    try:
        ec2 = boto3.client('ec2')
        regions = list(map(lambda x: x['RegionName'], ec2.describe_regions()['Regions']))
        return regions
    except Exception as e:
        logger.error(e)
        raise

def enable_ebs_encryption_by_default(regions: List[str]) -> None:
    for region_name in regions:
        ec2 = boto3.client("ec2", region_name=region_name)
        try: 
            ec2.enable_ebs_encryption_by_default()
            logger.info(f"Succeeded to enable ebs_encryption by default@{region_name}")
        except Exception as e:
            logger.info(f"Failed to enable ebs_encryption by default@{region_name}")
            logger.error(e)

def is_ebs_encryption_by_default(regions: List[str]) -> bool:
    check_regions = {}
    for region_name in regions:
        ec2 = boto3.client("ec2", region_name=region_name)
        try:
            res = ec2.get_ebs_encryption_by_default()
            check_regions[region_name] = res["EbsEncryptionByDefault"]
        except Exception as e:
            logger.error(f"{e}:{region_name}")
            check_regions[region_name] = False
    return all(check_regions.values())

def lambda_handler(event, context):

    #全リージョン取得
    regions=describe_regions()
    
    #EBSデフォルト暗号化の有効化
    enable_ebs_encryption_by_default(regions)

    is_resources = {
        "ebs_encryption_by_default": False,
    }
    is_resources["ebs_encryption_by_default"] = is_ebs_encryption_by_default(regions)

    if not all(is_resources.values()):
        logger.error("Failed to enable ebs_encryption by default")
        logger.error(
            f"is_resources: {is_resources}"
        )
        raise Exception('Fail to check resource')

    logger.info("Completed to enable ebs_encryption by default")
    logger.info(
        f"is_resources: {is_resources}"
    )
    return {
        "is_resources": is_resources
    }

EBSデフォルト暗号化を全リージョン無効化する

実際に利用する際にはテストのために無効化したいこともあると思うので、全リージョン無効化できるコードも置いておきます。こちらはリソースの状態チェックまではしてません。

import boto3
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def describe_regions() -> list:
    try:
        ec2 = boto3.client('ec2')
        regions = list(map(lambda x: x['RegionName'], ec2.describe_regions()['Regions']))
        return regions
    except Exception as e:
        logger.error(e)
        raise
def disable_ebs_encryption_by_default(regions):
    for region in regions:
        ec2 = boto3.client('ec2', region_name=region)
        try:
            ec2.disable_ebs_encryption_by_default()
            logger.info(
                f'Succeeded in disable ebs encryption by default@{region}')
        except Exception as e:
            logger.error(e)
        
def lambda_handler(event, context):

    #全リージョン取得
    regions=describe_regions()
    #EBSデフォルト暗号化の無効化
    disable_ebs_encryption_by_default(regions)

やってみる

有効化

以下のようにEBSデフォルト暗号化が無効になっている状態です。

それでは先ほどのコードを使ってEBSデフォルト暗号化を実行してみます。LambdaのIAMロールや実行時間は適宜調整してください。

有効化用のコードを貼り付けてDeployした状態です。テストイベントはデフォルトのまま実行します。

実行が完了すると、以下のようにレスポンスや実行ログが出力されます。

Responseにはリソースの状態が出力されます。成功していればebs_encryption_by_defaultの値にtrueが入っているはずです。

Function Log には各リージョンごとの有効化が成功したことを示すログを出力しています。

改めてEBSデフォルト暗号化の設定を確認すると、有効化されていることが確認できました。

無効化

有効化したEBSデフォルト暗号化を無効化します。先ほど紹介した無効化用のコードをLambdaで実行します。

有効化の時と同じようにLambdaを作成して実行してみます。

実行するとレスポンスはなく、各リージョンでEBSデフォルト暗号化の無効化に成功したメッセージが出力されています。

コンソールから確認してみると、ちゃんと無効化されていることが確認できました。

おわりに

LambdaからEBSデフォルト暗号化を全リージョン有効化(無効化)してみました。ログのメッセージ等は自由にカスタマイズしてご利用頂ければ幸いです。

StepFunctionsと組み合わせることで、アカウントのセットアップなどを自動化することもできます。Control Tower環境であればAssumeRoleする処理を入れることで、アカウント発行時の自動化も可能なのでご検討ください。