AWS Config Rules で Lambda function に渡されるイベント情報について

記事タイトルとURLをコピーする


みなさんこんにちは。
技術研究課の山田です。

この記事は AWS Advent Calendar 2015 の 9日目の内容になります。
Advent Calender に参加するのは初めてなので、なにとぞお手柔らかにお願いします。

さて、今回は AWS Config Rules のちょっとした小ネタをご紹介します。
AWS Config Rules とは? については前回の記事をご参照下さい。

Customer Managed Rules

AWS Config Rules には Customer Managed Rules という、独自ルールを作成して「特定のAWSリソースがポリシーを満たしているかどうか」検査する機能があります。
事前に Lambda function でルールを定義することで、AWSリソースの変更時または定期的に関数が実行され、リソースが適切な状態なのかチェックするという仕組みです。

Lambda function について

Customer Managed Rule の Lambda function で実行されるハンドラーの引数は eventcontext と、2つあります。

Lambda 関数ハンドラー (Node.js)
 

exports.myHandler = function(event, context) {

   ...

}

 

event はイベントソース( Lambda function の呼び出し元 )からのイベントデータが渡されます。
context は自身のランタイム情報が渡されます。

Customer Managed Rule で指定した Lambda function が呼び出されるタイミングとして、先ほども書いたように「リソース変更時」と「定期実行」の2パターンあるのですが、呼びだされたタイミングで上記の event引数 へ「監視リソースの状態」の情報が入っているJSONが渡されます。

この渡された JSON を関数内であれこれすることで、独自ルールを定義することになります。

event の中身について

前置きはこれくらいにして、event の中身を覗いてみましょう。
ドキュメントによると、event は次の4つのプロパティで構成されているようです。

Example AWS Lambda Functions for AWS Config Rules (Node.js)

invokingEvent : 監視するAWSリソースの状態
ruleParameters : 事前定義したパラメータセット
resultToken : ルール評価結果を特定するためのトークン
eventLeftScope : 監視するAWSリソースが削除されたのかどうか
event の中身は下記コードで確認します。
 

exports.handler = function(event, context) {
    console.log(event.invokingEvent);
    console.log(event.ruleParameters);
    console.log(event.resultToken);
    console.log(event.eventLeftScope);
)};


結果

下記パラメータを AWS Config Rules で設定した上で、t2.small のインスタンスを起動します。

また、Rule parameters ( ルールのチェック処理に引き渡すパラメーターを Key, Value の形式で設定する )には下記パラメータを設定しました。

 

出力結果です。 invokingEvent

{
    "configurationItemDiff": {
        "changedProperties": {},
        "changeType": "CREATE"
    },
    "configurationItem": {
        "configurationItemVersion": "1.1",
        "configurationItemCaptureTime": "2015-11-26T07:46:09.663Z",
        "configurationStateId": 1,
        "relatedEvents": [
            "xxxxxxx-013c-xxxxxx-8675-13fxxxxxxxxxxx"
        ],
        "awsAccountId": "xxxxxxxxxxxx",
        "configurationItemStatus": "ResourceDiscovered",
        "resourceId": "i-xxxxxxxx",
        "resourceName": null,
        "ARN": "arn:aws:ec2:us-east-1:xxxxxxxxxxxx:instance/i-xxxxxxxx",
        "awsRegion": "us-east-1",
        "availabilityZone": "us-east-1c",
        "configurationStateMd5Hash": "xxxxxxxxxxxxxxx",
        "resourceType": "AWS::EC2::Instance",
        "resourceCreationTime": "2015-11-26T07:39:36.000Z",
        "tags": {},
        "relationships": [
            {
                "resourceId": "eni-xxxxxxxxx",
                "resourceName": null,
                "resourceType": "AWS::EC2::NetworkInterface",
                "name": "Contains NetworkInterface"
            },
            {
                "resourceId": "sg-xxxxxxxx",
                "resourceName": null,
                "resourceType": "AWS::EC2::SecurityGroup",
                "name": "Is associated with SecurityGroup"
            },
            {
                "resourceId": "subnet-xxxxxxxx",
                "resourceName": null,
                "resourceType": "AWS::EC2::Subnet",
                "name": "Is contained in Subnet"
            },
            {
                "resourceId": "vol-xxxxxxxx",
                "resourceName": null,
                "resourceType": "AWS::EC2::Volume",
                "name": "Is attached to Volume"
            },
            {
                "resourceId": "vpc-xxxxxxxx",
                "resourceName": null,
                "resourceType": "AWS::EC2::VPC",
                "name": "Is contained in Vpc"
            }
        ],
        "configuration": {
            "instanceId": "i-xxxxxxxx",
            "imageId": "ami-60b6c60a",
            "state": {
                "code": 16,
                "name": "running"
            },
            "privateDnsName": "ip-172-31-13-xxx.ec2.internal",
            "publicDnsName": "ec2-52-23-xxx-xxx.compute-1.amazonaws.com",
            "stateTransitionReason": "",
            "keyName": "test",
            "amiLaunchIndex": 0,
            "productCodes": [],
            "instanceType": "t2.small",
            "launchTime": "2015-11-26T07:39:36.000Z",
            "placement": {
                "availabilityZone": "us-east-1c",
                "groupName": "",
                "tenancy": "default",
                "hostId": null,
                "affinity": null
            },
            "kernelId": null,
            "ramdiskId": null,
            "platform": null,
            "monitoring": {
                "state": "disabled"
            },
            "subnetId": "subnet-xxxxxxxx",
            "vpcId": "vpc-xxxxxxxx",
            "privateIpAddress": "xx.xx.xx.xx",
            "publicIpAddress": "52.23.151.xxx",
            "stateReason": null,
            "architecture": "x86_64",
            "rootDeviceType": "ebs",
            "rootDeviceName": "/dev/xvda",
            "blockDeviceMappings": [
                {
                    "deviceName": "/dev/xvda",
                    "ebs": {
                        "volumeId": "vol-xxxxxxxx",
                        "status": "attached",
                        "attachTime": "2015-11-26T07:39:40.000Z",
                        "deleteOnTermination": true
                    }
                }
            ],
            "virtualizationType": "hvm",
            "instanceLifecycle": null,
            "spotInstanceRequestId": null,
            "clientToken": "xxxxxxxxxxxxxxx",
            "tags": [],
            "securityGroups": [
                {
                    "groupName": "xxxxxxxxxxxx",
                    "groupId": "sg-xxxxxxxx"
                }
            ],
            "sourceDestCheck": true,
            "hypervisor": "xen",
            "networkInterfaces": [
                {
                    "networkInterfaceId": "eni-xxxxxxxxx",
                    "subnetId": "subnet-xxxxxxxx",
                    "vpcId": "vpc-xxxxxxxx",
                    "description": "",
                    "ownerId": "xxxxxxxxxxxx",
                    "status": "in-use",
                    "macAddress": "xx:98:94:xx:xx:xx",
                    "privateIpAddress": "xx.xx.xx.xx",
                    "privateDnsName": "ip-172-31-13-xxx.ec2.internal",
                    "sourceDestCheck": true,
                    "groups": [
                        {
                            "groupName": "xxxxxxxxxxxx",
                            "groupId": "sg-xxxxxxxx"
                        }
                    ],
                    "attachment": {
                        "attachmentId": "eni-attach-9a225477",
                        "deviceIndex": 0,
                        "status": "attached",
                        "attachTime": "2015-11-26T07:39:36.000Z",
                        "deleteOnTermination": true
                    },
                    "association": {
                        "publicIp": "52.23.151.xxx",
                        "publicDnsName": "ec2-52-23-xxx-xxx.compute-1.amazonaws.com",
                        "ipOwnerId": "amazon"
                    },
                    "privateIpAddresses": [
                        {
                            "privateIpAddress": "xx.xx.xx.xx",
                            "privateDnsName": "ip-172-31-13-xxx.ec2.internal",
                            "primary": true,
                            "association": {
                                "publicIp": "52.23.151.xxx",
                                "publicDnsName": "ec2-52-23-xxx-xxx.compute-1.amazonaws.com",
                                "ipOwnerId": "amazon"
                            }
                        }
                    ]
                }
            ],
            "iamInstanceProfile": null,
            "ebsOptimized": false,
            "sriovNetSupport": null
        }
    },
    "notificationCreationTime": "2015-11-26T07:46:10.944Z",
    "messageType": "ConfigurationItemChangeNotification",
    "recordVersion": "1.2"
}

 


ruleParameters
 

{
    "desiredInstanceType": "t2.micro"
}


resultToken
 

eyJlbmNyeXB0ZWREYXRhIjpbLTY ...

 

eventLeftScope
 

false

 

今回は Trigger type を Configuration changes にしたので、EC2を作成したタイミングで Lambda function が実行され、上記結果が出力されました。
invokingEvent にはAWSリソース( EC2 Instance )の情報、ruleParameters には事前に定義した値が取得出来ています。

まとめ

Lambda Function の中ならデフォルトで AWS SDK が使える状態なので、本当に自由にルール定義できちゃいますね。
この記事が誰かの何かに役立てば幸いです。