のぴぴのメモ

自分用のLinuxとかの技術メモ

AWS Security Hubのマルチアカウント一括設定スクリプトを使ってみる

はじめに

AWSが提供しているAWS Security Hubの一括設定ツールを試したのでそのメモです。
なんでこのツールを利用したかと言うと、AWS Security Hubはリージョン単位のサービスのためリージョンごとの設定が必要で、かつマルチアカウント構成の場合アカウント毎の設定になるので、作業量が「対象AWSアカウント数 x 対象リージョン数」となり手動でのセットアップは骨が折れるので、楽をしたいと言うのが発端です。

ツール

AWS Security Hubのマルチアカウント一括設定ツール
github.com

上記ツールですが、下記のマネコンAWS Security Hubの「設定」で出る「GitHubスクリプトを実行します」のリンク先のスクリプトになります。

構成環境

作成するAWS Security Hub構成

マルチアカウントのベストプラクティスである Landing Zoneにならい、下記アカウントがあるマルチアカウント構成を前提とします。

  • 支払いアカウント(OrganizationsのMaster Account)
  • メンバーアカウント
    • 監査アカウント
    • ログアカウント(CloudTrailのログなどを集中的に保管管理するアカウント)
    • 複数のリソースアカウント(VPCやEC2をデプロイする環境)

AWS Security Hubは、監査アカウントをMasterアカウントとして、他のアカウントはメンバーアカウントとして招待し作成したHubに所属させます。
f:id:nopipi:20200121231214p:plain

ツールの実行環境と実行用IAMロール

ツール実行に利用するIAMロールとインスタンス構成を説明します。 これらは手順の中で作成します。

  • IAMロール
    • ManageSecurityHubRole : Security Hubなどの実際の作業用に利用するIAMロール
    • ManageSecurityHubInstanceRole : スクリプトを実行するインスタンスに割り当てる、インスタンスロール。ManageSecurityHubRoleへのAssumeRoleのみ許可。

f:id:nopipi:20200121234222p:plain

作業前提

  • 作業環境
    • bashが動作する環境(Linux or Mac)であること
    • AWS CLIのインストールと各AWSアカウントへのアクセスのセットアップが完了していること
  • インスタンス環境
    • インスタンスを起動させるVPC、Subnet、SecurityGroupが事前準備されていること
    • VPCからインターネットアクセスできること

準備: IAMロールの作成

全アカウントにツールを実行するためのIAMロールを作成します。
Gitに含まれるCloudFormation(EnableSecurityHub.yaml)で、IAMロールを作成することもできますが、ここではCLIで作成しています。

事前準備

PROFILE=<auditアカウントのIAM管理可能なプロファイル>

監査アカウントのインスタンスIAMロール

スクリプトを実行するEC2にアタッチするインスタンスロールを作成します。

ASSUMEROLE_POLICY='{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}'

ROLE_POLICY='{
    "Version": "2012-10-17",
    "Statement": [
        {
           "Sid": "AssumeToManageSecurityHubRoleOfMemberAccounts",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::*:role/ManageSecurityHubRole"
        }
    ]
}'
#IAMロールの作成
aws --profile ${PROFILE} \
    iam create-role \
        --role-name "ManageSecurityHubInstanceRole" \
        --assume-role-policy-document "${ASSUMEROLE_POLICY}" \
        --max-session-duration 3600

#インラインポリシーのアタッチ
aws --profile ${PROFILE} \
    iam put-role-policy \
        --role-name "ManageSecurityHubInstanceRole" \
        --policy-name "ManageSecurityHubPolicy" \
        --policy-document "${ROLE_POLICY}"

#インスタンスプロファイルの作成
aws --profile ${PROFILE} \
    iam create-instance-profile \
        --instance-profile-name "ManageSecurityHubInstanceRole";

aws --profile ${PROFILE} \
    iam add-role-to-instance-profile \
        --instance-profile-name "ManageSecurityHubInstanceRole" \
        --role-name "ManageSecurityHubInstanceRole" ;


#IAMロールのARN取得
ARN_ManageSecurityHubInstanceRole=$(
    aws --profile ${PROFILE} --output text \
        iam get-role --role-name "ManageSecurityHubInstanceRole" \
        --query 'Role.Arn' )

echo ${ARN_ManageSecurityHubInstanceRole}

Security Hub管理用のIAMロール

各アカウントに、Security Hub管理用のIAMロールを作成します。
このIAMロールは、先に作成した「監査アカウントのインスタンスIAMロール」と信頼関係を結びます。

#一連の設定をSecurity Hubを利用する全AWSアカウントに設定します。
PROFILE=<対象のAWSアカウントのIAM管理者のプロファイル>

ASSUMEROLE_POLICY='{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
            "'"${ARN_ManageSecurityHubInstanceRole}"'"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}'

ROLE_POLICY='{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Condition": {
                "StringLike": {
                    "iam:AWSServiceName": [
                        "securityhub.amazonaws.com",
                        "config.amazonaws.com"
                    ]
                }
            },
            "Action": "iam:CreateServiceLinkedRole",
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": "securityhub:*",
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "config:DescribeConfigurationRecorders",
                "config:DescribeDeliveryChannels",
                "config:DescribeConfigurationRecorderStatus",
                "config:DeleteConfigurationRecorder",
                "config:DeleteDeliveryChannel",
                "config:PutConfigurationRecorder",
                "config:PutDeliveryChannel",
                "config:StartConfigurationRecorder"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": "iam:PassRole",
            "Resource": "arn:aws:iam::*:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:CreateBucket",
                "s3:PutBucketPolicy",
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::config-bucket-*",
            "Effect": "Allow"
        }
    ]
}'

#IAMロールの作成
aws --profile ${PROFILE} \
    iam create-role \
        --role-name "ManageSecurityHubRole" \
        --assume-role-policy-document "${ASSUMEROLE_POLICY}" \
        --max-session-duration 3600

#インラインポリシーのアタッチ
aws --profile ${PROFILE} \
    iam put-role-policy \
        --role-name "ManageSecurityHubRole" \
        --policy-name "ManageSecurityHubPolicy" \
        --policy-document "${ROLE_POLICY}"

スクリプト実行環境作成

auditアカウントに、スクリプト実行用のEC2環境を準備します。

プロファイル準備

PROFILE=<auditアカウントのEC2管理可能なプロファイル>

インスタンスの起動

#起動パラメータ設定(環境に合わせて変更するもの)
KEYNAME="CHANGE_KEY_PAIR_NAME" #環境に合わせてキーペア名を設定してください。  
SUBNETID=subnet-f59858bd  #"パブリックサブネットのIDを設定"
SG_ID=sg-071417e793b795090  #"SSHログインできるセキュリティーグループのIDを設定"

#起動パラメータ設定(固定設定)
INSTANCE_TYPE="t2.micro"
AL2_AMIID=$(aws --profile ${PROFILE} --output text \
    ec2 describe-images \
        --owners amazon \
        --filters 'Name=name,Values=amzn2-ami-hvm-2.0.????????.?-x86_64-gp2' \
                  'Name=state,Values=available' \
        --query 'reverse(sort_by(Images, &CreationDate))[:1].ImageId' ) ;

#タグ設定
TAGJSON='
[
    {
        "ResourceType": "instance",
        "Tags": [
            {
                "Key": "Name",
                "Value": "SecurityHubMgr"
            }
        ]
    }
]'

#ユーザデータ設定
USER_DATA='
#!/bin/bash -xe

#RPM最新化&ホスト名設定          
yum -y update
hostnamectl set-hostname SecurityHubMgr

#パッケージインストール
yum -y install python2-pip python2 git

#boto3インストール
sudo pip install boto3

#AWS CLIアップデート
curl -o "get-pip.py" "https://bootstrap.pypa.io/get-pip.py" 
python get-pip.py
pip install --upgrade

# ec2-userのAWS CLI初期設定
Region=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/.$//')
sudo -u ec2-user aws configure set region ${Region}
sudo -u ec2-user aws configure set output json

#スクリプトのセットアップ
cd /home/ec2-user
sudo -u ec2-user git clone https://github.com/awslabs/aws-securityhub-multiaccount-scripts.git
'

#インスタンスの起動
aws --profile ${PROFILE} \
    ec2 run-instances \
        --image-id ${AL2_AMIID} \
        --instance-type ${INSTANCE_TYPE} \
        --key-name ${KEYNAME} \
        --subnet-id ${SUBNETID} \
        --security-group-ids ${SG_ID} \
        --associate-public-ip-address \
        --iam-instance-profile "Name=ManageSecurityHubInstanceRole" \
        --tag-specifications "${TAGJSON}" \
        --user-data "${USER_DATA}" \
        --monitoring Enabled=true ;

スクリプトによるSecurityHubの有効化

Security Hub管理インスタンスへのログイン

MgrIP=$(aws --profile ${PROFILE} --output text \
    ec2 describe-instances  \
        --filters "Name=tag:Name,Values=SecurityHubMgr" "Name=instance-state-name,Values=running" \
    --query 'Reservations[*].Instances[*].PublicIpAddress' )

ssh ec2-user@${MgrIP}

SecurityHubのメンバーアカウント一覧(CSV)作成

Security Hubの有効化し、SecurityHubのMasterAccount(ここではauditアカウント)の配下のメンバーとなるAWSアカウントの一覧をCSV形式で作成します。1行1アカウントで、"AccountId,EmailAddress"形式で作成します。

CSVファイルの作成例(securityhub_account_list.csv)

111111111111,master@mail_address
222222222222,logging@mail_address
333333333333,resource1@mail_address
444444444444,resource2@mail_address

有効化対象リージョンの設定

スクリプトのデフォルトではSecurityHubが利用可能な全てのリージョンで有効化をしようとします。しかし、最近開設されたリージョンは、デフォルトではリージョン自身が無効化されており、そのまま実行するとスクリプトがエラーとなります。そのため、SecurityHubを有効化するリージョンを明示的に指定する必要があります。

Security Hubが利用可能なリージョン一覧の確認

CLIではコマンドがないので、boto3を利用しpythonワンライナーでSecurityHubが利用可能なリージョン一覧を取得します。

python -c "import boto3,json; print('{}'.format( json.dumps( boto3.session.Session().get_available_regions('securityhub') ) ) );"
有効化対象リージョン一覧作成

上記で取得した一覧情報から、有効化対象のリージョンを抽出し、カンマ区切りの文字列にします。

  • 変更点
    • デフォルトで無効化されているリージョンを削除。
    • カンマカンマ
ENABLE_REGIONS="ap-northeast-1,ap-northeast-2,ap-south-1,ap-southeast-1,ap-southeast-2,ca-central-1,eu-central-1,eu-north-1,eu-west-1,eu-west-2,eu-west-3,sa-east-1,us-east-1,us-east-2,us-west-1,us-west-2"

Security Hubの有効化

enablesecurityhub.pyスクリプトを利用し、対象アカウントの対象リージョンのSecurity Hub有効化を行います。

# Security Hubのマスターアカウントとして監査アカウントを指定
MASTER_ACCOUNT=$(aws sts get-caller-identity --output text --query 'Account')

#その他設定
ASSUME_ROLE="ManageSecurityHubRole"
CSV_FILE_NAME="securityhub_account_list.csv"

#実行
python2 ./aws-securityhub-multiaccount-scripts/enablesecurityhub.py \
    --master_account ${MASTER_ACCOUNT} \
    --assume_role ${ASSUME_ROLE} \
    --enabled_regions ${ENABLE_REGIONS} \
    ${CSV_FILE_NAME} ;

下記のようにスクリプトでのAWS Config有効化に失敗したAWSアカウント/リージョンがある場合、マネージメントコンソールのAWS Configで手動でConfigの有効化をしてから、enablesecurityhub.pyを再実行してください。

スクリプトによるSecurityHubの無効化

SecurityHubの無効化です。

MASTER_ACCOUNT=$(aws sts get-caller-identity --output text --query 'Account')
ENABLE_REGIONS="ap-northeast-1,ap-northeast-2,ap-south-1,ap-southeast-1,ap-southeast-2,ca-central-1,eu-central-1,eu-north-1,eu-west-1,eu-west-2,eu-west-3,sa-east-1,us-east-1,us-east-2,us-west-1,us-west-2"

#無効化実行
python2 ./aws-securityhub-multiaccount-scripts/disablesecurityhub.py \
    --master_account ${MASTER_ACCOUNT} \
    --assume_role ${ASSUME_ROLE} \
    --enabled_regions ${ENABLE_REGIONS}  \
    ${CSV_FILE_NAME} ;