VPCのIPv4 CIDRブロック設定値をAWS Configのカスタムルールでチェックする

2021.08.05

いわさです。

先日、VPCのIPv4 CIDRブロックへ設定する値を制限や統制する方法がないかと考えていたときに、AWS Configを使ってみようかと思いつきました。
そこでまずはConfigのカスタムルールを作成しVPCのCIDRをチェック出来るか確認してみることにしました。

Configは有効化する

まずは、Configを有効化します。これをしないと始まらないので。
有効化の際に、VPCを監視対象リソースに指定することを忘れないようにします。

有効化したら、新規VPCを作成してみます。
少し時間がかかりますがタイムラインにイベントが表示されると思います。

履歴が表示されるようになったら、get-resource-config-historyコマンドを使って、イベント情報を取得しましょう。
後ほどLambda関数でオブジェクトにアクセスしますので構造を知っておく必要があります。

[cloudshell-user@ip-10-0-166-215 ~]$ aws configservice get-resource-config-history --resource-type AWS::EC2::VPC --resource-id vpc-07af0f143471606d1
{
    "configurationItems": [
        {
            "version": "1.3",
            "accountId": "123456789012",
            "configurationItemCaptureTime": "2021-08-03T12:47:40.227000+00:00",
            "configurationItemStatus": "ResourceDiscovered",
            "configurationStateId": "1627994860227",
            "configurationItemMD5Hash": "",
            "arn": "arn:aws:ec2:ap-northeast-1:123456789012:vpc/vpc-07af0f143471606d1",
            "resourceType": "AWS::EC2::VPC",
            "resourceId": "vpc-07af0f143471606d1",
            "awsRegion": "ap-northeast-1",
            "availabilityZone": "Multiple Availability Zones",
            "tags": {
                "Name": "hige"
            },
            "relatedEvents": [],
            "relationships": [
                {
                    "resourceType": "AWS::EC2::SecurityGroup",
                    "resourceId": "sg-07333c5a9149eaf97",
                    "relationshipName": "Contains SecurityGroup"
                },
                {
                    "resourceType": "AWS::EC2::RouteTable",
                    "resourceId": "rtb-06b882331843997c8",
                    "relationshipName": "Contains RouteTable"
                },
                {
                    "resourceType": "AWS::EC2::NetworkAcl",
                    "resourceId": "acl-07664aa036e353aef",
                    "relationshipName": "Contains NetworkAcl"
                }
            ],
            "configuration": "{\"cidrBlock\":\"1.2.3.0/24\",\"dhcpOptionsId\":\"dopt-9c6f63fb\",\"state\":\"available\",\"vpcId\":\"vpc-07af0f143471606d1\",\"ownerId\":\"123456789012\",\"instanceTenancy\":\"default\",\"ipv6CidrBlockAssociationSet\":[],\"cidrBlockAssociationSet\":[{\"associationId\":\"vpc-cidr-assoc-035a10329f38a8ef3\",\"cidrBlock\":\"1.2.3.0/24\",\"cidrBlockState\":{\"state\":\"associated\",\"statusMessage\":null}}],\"isDefault\":false,\"tags\":[{\"key\":\"Name\",\"value\":\"hige\"}]}",
            "supplementaryConfiguration": {}
        }
    ]
}

ちなみにあとから気づいたのですが、上記はマネコンからでも取得出来ます。

Lambda関数を作成する。でもとても簡単

さて、確認出来たらカスタムルールをLambdaで作成しましょう。
この辺りから気が重くなりそうだったのですが、作成すると言っても実は結構簡単でした。

ブループリントのひな形から関数を作成し、evaluateChangeNotificationComplianceメソッドを修正するだけで良いです。
ブループリントはNode.jsのものが用意されております。

以下を修正します。

準拠していればCOMPLIANT、非準拠であればNON_COMPLIANTを返します。

function evaluateChangeNotificationCompliance(configurationItem, ruleParameters) {
    checkDefined(configurationItem, 'configurationItem');
    checkDefined(configurationItem.configuration, 'configurationItem.configuration');
    checkDefined(ruleParameters, 'ruleParameters');

    if (configurationItem.resourceType !== 'AWS::EC2::VPC') {
        return 'NOT_APPLICABLE';
    } else if ("10.0.0.0/16" === configurationItem.configuration.cidrBlock) {
        return 'COMPLIANT';
    }
    return 'NON_COMPLIANT';
}

本当はRFC1918に準拠をしているのかチェックしたかったのですが、すぐ良い方法が浮かばなかったのでやめました。
NPMの何か使ってサクッとやれないものか。別途検討したいと思います(いつか、きっと)

Configのカスタムルールで指定して動作確認

関数が作成出来たらアップロードし、ConfigのカスタムルールでLambda関数のARNを指定します。
トリガーリソースにAWS EC2 VPCを選択します。

試しにVPCを作成してみましょう。

VPCは作成されましたが、Configルールに結果が表示されませんでした。

Configの操作権限を追加

トラブルシューティングしてみましょう。
Lambda関数は実行されているかを確認します。
モニタリング画面を見ると実行はされてそうです。

ログを見てみましょう。

エラーが出力されていました。
どうやら権限が足りてないようです。

config:PutEvaluationsが必要なようです。

Lambda関数の実行ロールに権限を付与します。
今回はConfig用の管理ポリシーを追加しました。

さて、再び非準拠なCIDRのVPCを新規作成してみましょう。

今度は無事検出されました!

まとめ

Configのカスタムルール使ってみたかったのですが、Lambda関数で作り込まなければいけないという印象から避けていました。
しかし、実際にやってみると雛形も用意されており、とても簡単に実装することが出来ました。
同じように少し構えてしまっていた方がいれば是非試してみてください。思ったより簡単だと思います。