こんにちは。AWS CLIが好きな福島です。
はじめに
今回は、先日あった以下のアップデートに関する内容をブログでご紹介いたします。
AWS Config rules now support proactive compliance
結論
- 今まで構成変更時または定期的という検知モードがあり、存在するリソースに対してConfig Rulesの準拠状況を確認できたが、プロアクティブモードのリリースにより、リソースのデプロイ前にConfig Rulesに準拠しているか確認できるようになった。
- つまり、Config Rulesは発見的統制に加え、予防的統制にも利用できるようになった。
- CloudFormationを利用している環境で有効活用できる。
- CloudFormation Guardを使っている方は、Config Rulesを利用することで自分たちでポリシーを定義する必要がなくなるかも。
- ただし、プロアクティブモードにサポートしているマネージドルールは、18種類。
- この機能は、CI/CDに組み込んだり、CloudFormation Hooksと合わせて利用することがユースケースとして挙げられるが、作りこみが多少必要になりそう。
- 全リージョンで利用できるようになる予定だが、もう少し時間がかかりそう。(2022/12/21現在、東京リージョンでは利用不可)
◆プロアクティブモードをサポートしているマネージドルール
- api-gw-xray-enabled - AWS Config
- autoscaling-group-elb-healthcheck-required - AWS Config
- ec2-instance-multiple-eni-check - AWS Config
- eip-attached - AWS Config
- elasticsearch-logs-to-cloudwatch - AWS Config
- elasticsearch-node-to-node-encryption-check - AWS Config
- lambda-function-settings-check - AWS Config
- lambda-inside-vpc - AWS Config
- rds-automatic-minor-version-upgrade-enabled - AWS Config
- rds-enhanced-monitoring-enabled - AWS Config
- rds-instance-public-access-check - AWS Config
- rds-multi-az-support - AWS Config
- rds-storage-encrypted - AWS Config
- redshift-cluster-maintenancesettings-check - AWS Config
- redshift-cluster-public-access-check - AWS Config
- s3-bucket-logging-enabled - AWS Config
- sns-encrypted-kms - AWS Config
- subnet-auto-assign-public-ip-disabled - AWS Config
試してみる
以下をチェックするConfig Rulesをプロアクティブモードで試してみます。
- RDSの暗号化が有効になっているか(rds-storage-encrypted)
- パブリックアクセスがオフになっているか(rds-instance-public-access-check)
今回はバージニア北部リージョンで試します。
参考 New – AWS Config Rules Now Support Proactive Compliance | AWS News Blog
①Config Rulesのマネージドルールの作成
- ルールを追加を押下
- rds-storage-encrypted を選択し、次へを押下
- Turn on proactive evaluation にチェックを付け、次へを押下
- 確認と作成の画面が表示されるため、ルールを追加を押下
- 同様の流れでrds-instance-public-access-checkのConfig Ruleも作成し、最終的に以下の通り、2つのルールが作られればOKです。
②プロアクティブにConfig Ruleの評価を行う
AWS CLIを利用し、プロアクティブにConfig Ruleを実行します。 AWS CLIのバージョンが古い場合、サブコマンドがない可能性があるため、必要に応じてバージョンアップをしてください。 私は、AWS CLI 2.9.8で試しております。
また、今回は以下の3つのサブコマンドを利用します。
start-resource-evaluation : プロアクティブにConfig Ruleの評価を行うコマンド get-resource-evaluation-summary : 評価結果のサマリを表示するコマンド get-compliance-details-by-resource : 評価結果の詳細を表示するコマンド
- プロアクティブにConfig Ruleを実行
以下のコマンドを実行します。
コマンドを実行すると、ResourceEvaluationIdが表示されます。評価結果を確認するためには、別のコマンドを実行する必要があります。
# aws configservice start-resource-evaluation --evaluation-mode PROACTIVE \ --resource-details '{"ResourceId":"myDB", "ResourceType":"AWS::RDS::DBInstance", "ResourceConfiguration":"{\"StorageEncrypted\":true,\"PubliclyAccessible\": false}", "ResourceConfigurationSchemaType":"CFN_RESOURCE_SCHEMA"}' \ --evaluation-timeout 60 { "ResourceEvaluationId": "57f2f294-bb3a-4fdc-8aac-9824d5c12e50-18532628946" } #
補足すると、どのConfig Rulesを実行するかは指定する必要がなく、リソースタイプに応じてプロアクティブモードのConfig Rulesが実行されます。
また、今回はResourceConfigurationにStorageEncrypted:trueとしか記載していませんが、実際に利用する際には、CloudFormationのProperties内に定義した値を指定して評価することになるかと思います。
- 評価結果の確認
--resource-evaluation-idには、先ほどのコマンドの実行結果で出力されたIDを指定して、コマンドを実行します。
以下の通り、「 "Compliance": "COMPLIANT",」になっていることを確認します。
# aws configservice get-resource-evaluation-summary --resource-evaluation-id 57f2f294-bb3a-4fdc-8aac-9824d5c12e50-18532628946 { "ResourceEvaluationId": "57f2f294-bb3a-4fdc-8aac-9824d5c12e50-18532628946", "EvaluationMode": "PROACTIVE", "EvaluationStatus": { "Status": "SUCCEEDED" }, "EvaluationStartTimestamp": "2022-12-21T10:53:16.650000+09:00", "Compliance": "COMPLIANT", "ResourceDetails": { "ResourceId": "myDB", "ResourceType": "AWS::RDS::DBInstance", "ResourceConfiguration": "{\"StorageEncrypted\":true,\"PubliclyAccessible\": false}" } } #
- 非準拠の場合を確認
StorageEncrypted に false を指定して、再度プロアクティブにConfig Ruleを実行します。
# aws configservice start-resource-evaluation --evaluation-mode PROACTIVE \ --resource-details '{"ResourceId":"myDB", "ResourceType":"AWS::RDS::DBInstance", "ResourceConfiguration":"{\"StorageEncrypted\":false,\"PubliclyAccessible\": false}", "ResourceConfigurationSchemaType":"CFN_RESOURCE_SCHEMA"}' \ --evaluation-timeout 60 { "ResourceEvaluationId": "a5ddf098-b0ec-47c8-b5e9-57c452e3a427-185326412a7" } #
そして先ほどと同様に評価結果を確認します。
すると、「 "Compliance": "NON_COMPLIANT",」になっていることを確認できます。
# aws configservice get-resource-evaluation-summary --resource-evaluation-id a5ddf098-b0ec-47c8-b5e9-57c452e3a427-185326412a7 { "ResourceEvaluationId": "a5ddf098-b0ec-47c8-b5e9-57c452e3a427-185326412a7", "EvaluationMode": "PROACTIVE", "EvaluationStatus": { "Status": "SUCCEEDED" }, "EvaluationStartTimestamp": "2022-12-21T10:54:57.367000+09:00", "Compliance": "NON_COMPLIANT", "ResourceDetails": { "ResourceId": "myDB", "ResourceType": "AWS::RDS::DBInstance", "ResourceConfiguration": "{\"StorageEncrypted\":false,\"PubliclyAccessible\": false}" } } #
上記では、どのConfig Rulesが非準拠になっているか分かりません。
その際に「get-compliance-details-by-resource」を利用することでConfig Rulesごとに評価結果を確認することができます。
これにより、rds-storage-encryptedのConfig Ruleが非準拠になっていることが分かります。
# aws configservice get-compliance-details-by-resource --resource-evaluation-id a5ddf098-b0ec-47c8-b5e9-57c452e3a427-185326412a7 { "EvaluationResults": [ { "EvaluationResultIdentifier": { "EvaluationResultQualifier": { "ConfigRuleName": "rds-instance-public-access-check", "ResourceType": "AWS::RDS::DBInstance", "ResourceId": "myDB", "EvaluationMode": "PROACTIVE" }, "OrderingTimestamp": "2022-12-21T10:55:27.403000+09:00", "ResourceEvaluationId": "a5ddf098-b0ec-47c8-b5e9-57c452e3a427-185326412a7" }, "ComplianceType": "COMPLIANT", "ResultRecordedTime": "2022-12-21T10:54:57.706000+09:00", "ConfigRuleInvokedTime": "2022-12-21T10:54:57.502000+09:00" }, { "EvaluationResultIdentifier": { "EvaluationResultQualifier": { "ConfigRuleName": "rds-storage-encrypted", "ResourceType": "AWS::RDS::DBInstance", "ResourceId": "myDB", "EvaluationMode": "PROACTIVE" }, "OrderingTimestamp": "2022-12-21T10:55:27.403000+09:00", "ResourceEvaluationId": "a5ddf098-b0ec-47c8-b5e9-57c452e3a427-185326412a7" }, "ComplianceType": "NON_COMPLIANT", "ResultRecordedTime": "2022-12-21T10:54:57.724000+09:00", "ConfigRuleInvokedTime": "2022-12-21T10:54:57.514000+09:00" } ] } #
実環境での利用を考える
前章でプロアクティブなConfig Rulesを利用するイメージは湧いたかと存じますが、実環境での利用は少しハードルがありそうではないでしょうか。
私が考えるに、CloudFormationを作り、いざプロアクティブにConfig Rulesの評価を行おうとなった際に、別途コマンドを用意しなければならない点がハードルかなと感じました。
ということで楽にチェックができるようにスクリプトを作ってみました。
注意点
JSONで記載されたCloudFormationのテンプレートにしか対応していません。yamlで記載している場合は、yqコマンドなどによりjsonに変換する必要があります。
また、CloudFormationのテンプレートにRefやSubといった組み込み関数が入っている場合、上手くいきませんでした。
これは、スクリプトの問題ではなく、おそらく、ConfigのAPIであるstart-resource-evaluationの仕様によるものだと思います。
仮に仕様によるものだとすれば、実環境で利用するにはもう少し時間がかかりそうです。
使い方
引数のCloudFormationのテンプレートを指定して使うことができます。 以下は、準拠の例です。
# ./config-rules-check.sh rds-template.json MyDB(AWS::RDS::DBInstance) : COMPLIANT(COMPLIANT: rds-storage-encrypted,rds-instance-public-access-check NON_COMPLIANT: None EVALUATION_ID: e08950fe-20bc-479b-bb2a-54317b747f6a-18532906b03) #
以下は、非準拠の例です。
# ./config-rules-check.sh rds-template.json MyDB(AWS::RDS::DBInstance) : NON_COMPLIANT(COMPLIANT: rds-storage-encrypted NON_COMPLIANT: rds-instance-public-access-check EVALUATION_ID: df222e34-108f-46eb-b769-140bc70837c4-18532914543) #
rds-template.jsonの中身(準拠)
{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "MyDB": { "Type": "AWS::RDS::DBInstance", "Properties": { "AllocatedStorage": "5", "DBInstanceClass": "db.t2.small", "Engine": "MySQL", "MasterUsername": "MyName", "MasterUserPassword": "MyPassword", "PubliclyAccessible": false, "StorageEncrypted": true }, "DeletionPolicy": "Snapshot" } } }
rds-template.jsonの中身(非準拠)
{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "MyDB": { "Type": "AWS::RDS::DBInstance", "Properties": { "AllocatedStorage": "5", "DBInstanceClass": "db.t2.small", "Engine": "MySQL", "MasterUsername": "MyName", "MasterUserPassword": "MyPassword", "PubliclyAccessible": true, "StorageEncrypted": true }, "DeletionPolicy": "Snapshot" } } }
スクリプト(config-rules-check.sh)の詳細
## 第1引数を定義 template=$1 ## チェック対象(サポートしているリソースタイプの一覧) grep_check="AWS::RDS::DBInstance|AWS::S3::Bucket|AWS::Redshift::Cluster|AWS::Elasticsearch::Domain|AWS::EC2::Subnet|AWS::SNS::Topic|AWS::AutoScaling::AutoScalingGroup|AWS::Lambda::Function|AWS::EC2::Instance|AWS::ApiGateway::Stage|AWS::EC2::EIP" ## CloudFormationのテンプレートからConfig Rulesのチェックに必要な値のみを取得 grep -v "#" $template | jq -r '.Resources|keys|@csv' | sed 's/\"//g' | tr "," "\n" | while read key do TYPE=$(grep -v "#" $template | jq -r --arg body $key .Resources.$key.Type) if [[ 0 == $(echo $TYPE | grep -Ew $grep_check | wc -l) ]] ; then echo "$key($TYPE)は、非サポートのためチェック対象外です。" continue fi CONFIGRATION=$(grep -v "#" $template | jq -r --arg body $key .Resources.$key.Properties | sed 's/"/\\\"/g' | tr "\n" " ") ## プロアクティブにConfig Rulesのチェックを行う EVALUATION_ID=$(cat << EOF | bash aws configservice start-resource-evaluation --evaluation-mode PROACTIVE \ --resource-details '{"ResourceId":"MyResource", "ResourceType":"${TYPE}", "ResourceConfiguration":"${CONFIGRATION}", "ResourceConfigurationSchemaType":"CFN_RESOURCE_SCHEMA"}' \ --evaluation-timeout 60 --query ResourceEvaluationId --output text EOF ) ## 評価待ち sleep 3 ## 評価結果の確認 COMPLIANCE=$(aws configservice get-resource-evaluation-summary --resource-evaluation-id ${EVALUATION_ID} --query Compliance --output text) COMPLIANCE_DETAIL=$(aws configservice get-compliance-details-by-resource --resource-evaluation-id ${EVALUATION_ID} \ --query "EvaluationResults[?ComplianceType=='COMPLIANT'].EvaluationResultIdentifier.EvaluationResultQualifier.ConfigRuleName" --output text | tr "\t" ",") NON_COMPLIANCE_DETAIL=$(aws configservice get-compliance-details-by-resource --resource-evaluation-id ${EVALUATION_ID} \ --query "EvaluationResults[?ComplianceType=='NON_COMPLIANT'].EvaluationResultIdentifier.EvaluationResultQualifier.ConfigRuleName" --output text | tr "\t" ",") if [[ -z $COMPLIANCE_DETAIL ]] ; then COMPLIANCE_DETAIL="None" elif [[ -z $NON_COMPLIANCE_DETAIL ]] ; then NON_COMPLIANCE_DETAIL="None" fi ## 評価結果の表示 echo "$key($TYPE) : $COMPLIANCE(COMPLIANT: $COMPLIANCE_DETAIL NON_COMPLIANT: $NON_COMPLIANCE_DETAIL EVALUATION_ID: $EVALUATION_ID)" done
感想
今回は、Config Rulesの新しい検知モードであるプロアクティブモードについて、ご紹介いたしました。
実環境で利用するには作りこみが必要であったり、ハードルは低くないように感じましたが、予防的統制としても、Config Rulesが利用できるようになったのは良いアップデートなのかなと思います。 今後のアップデートに期待ですね!