AWS ConfigとLambdaを組み合わせて運用監視を楽にする – ClassmethodサーバーレスAdvent Calendar 2017 #serverless #adventcalendar

2017.12.05

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

どうも!大阪オフィスの西村祐二です。

このエントリはServerless Advent Calendar 2017 5日目の記事です。

人はどれだけ注意を払っていても必ずミスをしてしまう生き物です。

作業中にうっかりオペミスをしてしまうことは誰にでもおこる可能性があります。 ミスに気づいたらまだマシですが、ミスに気づかず、放置してしまうと大きなインシデントに繋がる可能性があります。

そういった場合を想定して、監視設定をおこなうのですが、 理想的な監視は異常があったら、管理者にメールなどで通知しつつ、 自動的にあるべき設定に戻してくれることかと思います。

AWS Configはサービスのあるべき姿を定義することができます。 Lambdaと組み合わせることで、理想的な運用監視ができるのではと思ったので 今回試してみます。

シナリオ

本来、セキュリティグループの22番ポートは閉じているけど、何かの拍子に22番ポートが開いた。 AWS Configでそれを検知し、自動的に管理者にメールを通知しつつLambdaで22番ポートを閉じる。

構成図

事前作業

・監視対象となるセキュリティグループを作成しておきます。 今回はタグに「test-config」と設定したセキュリティグループを作成しておきました。

・SNS Topicを作成し、通知したいメールを設定しておきます。 今回は「test-config-topic」というトピックを作成しておきました。

設定方法についてはこちらのドキュメントを参照ください。

AWS Configの設定

マネージメントコンソールのAWS Configから設定を行っていきます。

設定

▼AWS Configで記録するリソースを「Security Group」にしておきます。

▼S3バケットを指定します。

▼事前に作成したSNSトピックを指定します。

▼ロールの設定を行い、保存します。

ダッシュボードから記録しているリソースを確認

ダッシュボードより、今回記録している「SecurityGroup」が表示されていることを確認します。 表示されるまでに少し時間がかかるかもしれません。

ルール設定

AWS Configで正しい設定かどうか判定を行うルールを設定します。

▼今回はデフォルトで用意されている「restricted-ssh」ルールをつかっていきます。

▼トリガータイプを「設定の変更」、変更範囲を「タグ」、「Name:test-config」と監視するセキュリティグループを設定し、保存します。

▼設定したルールがきちんと設定されたか確認します。 「準拠」となっていることを確認します。

Lambdaの設定

AWS Configにて設定変更を検知したときに、実行されるSNSをトリガーとして、 追加されたセキュリティグループの設定をLambdaにて正しい設定に戻します。(追加設定を削除します。)

SNSからわたってくるデータの一部

From SNS:
{
    "awsAccountId": "XXXXXXXXXXXXXX",
    "configRuleName": "restricted-ssh",
    "configRuleARN": "arn:aws:config:ap-northeast-1:XXXXXXXXXXXX:config-rule/config-rule-XXXXXXXXXXX",
    "resourceType": "AWS::EC2::SecurityGroup",
    "resourceId": "sg-XXXXXXXX",
    "awsRegion": "ap-northeast-1",
    "newEvaluationResult": {
        "evaluationResultIdentifier": {
            "evaluationResultQualifier": {
                "configRuleName": "restricted-ssh",
                "resourceType": "AWS::EC2::SecurityGroup",
                "resourceId": "sg-XXXXXXXXX"
            },
            "orderingTimestamp": "2017-XX-XXTXX:XX:XX.083Z"
        },
        "complianceType": "NON_COMPLIANT",
        "resultRecordedTime": "2017-XX-XXTXX:XX:XX.083Z",
        "configRuleInvokedTime": "2017-XX-XXTXX:XX:XX.083Z",
        "annotation": null,
        "resultToken": null
    },
    "oldEvaluationResult": {
        "evaluationResultIdentifier": {
            "evaluationResultQualifier": {
                "configRuleName": "restricted-ssh",
                "resourceType": "AWS::EC2::SecurityGroup",
                "resourceId": "sg-b5a36fcc"
            },
            "orderingTimestamp": "2017-XX-XXTXX:XX:XX.083Z"
        },
        "complianceType": "COMPLIANT",
        "resultRecordedTime": "2017-XX-XXTXX:XX:XX.083Z",
        "configRuleInvokedTime": "2017-XX-XXTXX:XX:XX.083Z",
        "annotation": null,
        "resultToken": null
    },
    "notificationCreationTime": "2017-XX-XXTXX:XX:XX.083Z",
    "messageType": "ComplianceChangeNotification",
    "recordVersion": "1.0"
}
  • ランタイム:python3.6
  • トリガー:「test-config-topic」AWS Configで設定したSNSトピック
  • ロール:RevokeSecurityGroupIngressを付与

下記がLambdaのサンプルプログラムになります。

"""This is sample."""
import json
import boto3

def lambda_handler(event, context):
    message = json.loads(event['Records'][0]['Sns']['Message'])
    id = message['resourceId']
    status = message['newEvaluationResult']['complianceType']
    if status == 'COMPLIANT':
        return 'end'

    ec2 = boto3.resource('ec2')
    security_group = ec2.SecurityGroup(id)
    response = security_group.revoke_ingress(
        IpPermissions=[
            {
                'FromPort': 22,
                'IpProtocol': 'tcp',
                'ToPort': 22,
                'IpRanges': [
                    {
                        'CidrIp': '0.0.0.0/0'
                    }
                ]
            }
        ]
    )
    print("Security Group Changed")
    return 'end'

動作確認

対象のセキュリティグループで22番ポートをあけてみます。

設定変更の検知まで多少時間がかかりますが、 件名:「[AWS Config:ap-northeast-1] AWS::EC2::SecurityGroup sg-XXX is NON_COMPLIANT with restricted-...」 の正しい設定ではない旨(NON_COMPLIANT)のメール通知がきます。

AWS ConfigでSNSが実行されるとLambdaによって追加された設定が削除されて、 正しい設定に戻す処理が自動で実行されます。

しばらく待つと、セキュリティグループが正しい設定(COMPLIANT)になった旨の メールがとどきます。

さいごに

いかがだったでしょうか。 AWS ConfigとLambdaを使ってセキュリティグループが意図しない設定に変更されたときに メールを送りつつ、自動で正しい設定に修復してみました。 これを発展させていけば、障害がおきても自動で復旧させる サーバーレスなオートメーション監視システムが作れるのではないでしょうか。

誰かの参考になれば幸いです。