Amazon Web Services ブログ

サーバレスワークフローとAmazon CloudWatchイベントでAWSリソースのタグ変更を監視する

イントロダクション

Amazon CloudWatchイベントは、AWSリソースのタグ変更をサポートするようになりました。この新しいCloudWatchイベントタイプを使用すると、タグ変更に適合するCloudWatchイベントルールを作成でき、AWS Lambda関数など複数のターゲットにルーティングすることで、ワークフローを自動で開始することができます。このブログ記事では、AWSリソースに対するタグ変更をセキュアに実施するための、AWS Lambdaを使用したコスト効率の高いサーバーレスソリューションを構築する例を示します。

タグ変更によるAmazon CloudWatchイベントの作成

Amazon CloudWatchイベントにより、AWSリソースの変化を表すほぼリアルタイムのシステムイベントストリームが得られます。多くのAWSリソースはタグをサポートしており、カスタムにユーザーが属性を生成できることにより、リソースを簡単に整理して分類することができます。タグの一般的なユースケースは、コスト割り当ての分類、アクセス制御のセキュリティ、および自動化です。 Amazon CloudWatchイベントを使用すると、タグの変更をモニタリングし、AWSリソースのタグの状態を追跡できます。以前は、継続的にAPIをポーリングし、複数のAPIコールを組み合わせることで、同様の機能を実現していました。今は、個々のサービスAPI、リソースグループのタグエディタ、およびリソースグループのタグ付けAPIからの変更を含む、いかなるタグ変更は、”Tag Change on Resource”イベントがトリガされます。次のコードは、新しいCloudWatchイベントの例です。

{
  "version": "0",
  "id": "bddcf1d6-0251-35a1-aab0-adc1fb47c11c",
  "detail-type": "Tag Change on Resource",
  "source": "aws.tag",
  "account": "123456789012",
  "time": "2018-09-18T20:41:38Z",
  "region": "us-east-1",
  "resources": [
    "arn:aws:ec2:us-east-1:123456789012:instance/i-0000000aaaaaaaaaa"
  ],
  "detail": {
    "changed-tag-keys": [
      "a-new-key",
      "an-updated-key",
      "a-deleted-key"
    ],
    "service": "ec2",
    "resource-type": "instance",
    "version": 3,
    "tags": {
      "a-new-key": "tag-value-on-new-key-just-added",
      "an-updated-key": "tag-value-was-just-changed",
      "an-unchanged-key": "tag-value-still-the-same"
    }
  }
}

全てのCloudWatchイベントは、同じトップレベルのフィールドを持ちます。

  • Version:デフォルトで、全てのイベントに0(zero)がセットされます。
  • Id:全てのイベントにユニークな値が生成されます。これは、ルールに従ってターゲットにて実施されたイベントの追跡に役立ちます。
  • detail-type:Sourceフィールドと組み合わせて、Detailフィールドに表示されるフィールドと値を識別します。
  • Source:イベントのソースとなるサービスを識別します。タグ変更のソースは ‘aws.tag’です。
  • Time:イベントのタイムスタンプです。
  • Region:イベントが発生したAWSリージョンを識別します。
  • Resources:イベントに関連するリソースを識別するAmazonリソースネーム(ARN)です。これは、タグが変更されたリソースを表します。
  • Detail:イベントタイプによって内容が異なります。リソースのタグ変更の場合、以下のDetailフィールドが含まれます。
    • Changed-tag-keys:このイベントで変更されたタグキーです。
    • Service:リソースが属しているサービスです。この例では、EC2です。
    • Resource-type:サービスのリソースタイプです。この例では、EC2 instanceです。
    • Version:タグセットのバージョンです。この値は1から開始され、タグが変わるとインクリメントされます。タグ変更イベントの順序を確認する際に役立ちます。
    • Tags:変更後の現在のリソースのタグを表します。

より詳細な情報を CloudWatch イベント のイベントパターンにて確認できます。

CloudWatchイベントは、異なるフィールドに基づいて、特定のイベントパターンに適合するルールを作成することができます。基本的な例を以下に示します。この例では、特定のタグがEC2インスタンスに関連付けられていない場合に、EC2インスタンスが自動的に停止します。 Amazon CloudWatchイベントのフィールドを使用して、EC2インスタンスのタグイベントと適合するパターンを作成し、AWS Lambda関数を起動します。

AWS Lambdaとサーバレス

AWS Lambdaは、サーバーのプロビジョニングや管理のオーバーヘッドなしに、クラウドでコードを実行できるサーバーレスのパラダイムです。サーバーを意識することなく、必要なときにのみコードを実行することができ、使用した時間に応じて支払いすることができます。サーバーレスと呼ばれていますが、サーバーがないわけではありません。つまり、ユーザー側でコードを実行するために使用されるサーバーをプロビジョニング、構成、または管理する必要がなくなり、多くの労力を節約できます。 AWS Lambdaの詳細については、AWS Lambda Product Overviewをご確認ください。

例:タグ変更をモニタリングし、必要なタグのないEC2インスタンスを自動で停止させる

増加するAWSリソースとAWSアカウントを管理するため、タグによってリソースを適切に分類することが容易になります。タグは、コストの割り当てやセキュリティなどの重要なユースケースによく使用されます。 AWSリソースを管理する場合は、すべてのリソースに一貫してタグを付ける必要があります。多くの場合、リソースがプロビジョニングされると、全ての適切なタグが付与されます。しかし、後のプロセスでは、会社のタグポリシーから逸脱したタグ変更が生じることがあります。タグの変更をモニタリングすることで、タグ変更を常に注視し、必要に応じて即時に対応することができます。これにより、すべてのリソースが適切に分類されていることを確実にできます。

EC2インスタンスに必要なタグが付与されていることを確認するための、EC2インスタンスのタグ変更をモニタリングする方法をさらに説明します。 EC2インスタンスのタグが変更され、必要なタグがなくなると、サーバーレステクノロジーを利用してEC2インスタンスを自動的にシャットダウンします。なぜこうするのかというと、すべてのリソースが会社のタグポリシーに従ってタグ付けされていることを確実にするためです。たとえば、これはコストの割り当てを容易にしてくれます。

この例では、JavaScriptとNode.js 6.10を使用し、またバージニア北部リージョン(us-east-1)にて実行します。匿名アカウントIDである123456789012 を使用します。

Step1. AWS Lambdaのセットアップ

AWS Lambdaコンソールにて、[関数の作成]をクリックし、[一から作成]をクリックします。以下のスクリーンショットに示すように、AutoEC2Terminationという名前のJavaScript関数を作成し、auto-stop-ec2-roleを割り当てます。

https://d2908q01vomqb2.cloudfront.net/972a67c48192728a34979d9a35164c1295401b71/2018/10/25/blog1-1024x665.png

‘index.js’からデフォルトコードを削除し、以下のコードを貼り付けます。その後保存します。

// Load the SDK for JavaScript
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'us-east-1'});
// Create EC2 service object
ec2 = new AWS.EC2({apiVersion: '2016-11-15'});

exports.handler = (event, context, callback) => {
  var detail = event.detail

  // no action if this event is not about ec2 instance
  if (!(detail["service"] === "ec2" && detail["resource-type"] === "instance")) return

  var tags = detail["tags"]

  console.log(tags)

  // if associated tags not contain the expected tag pair
  if (!tags.hasOwnProperty("valid-key") || tags["valid-key"] !== "valid-value"){
    console.log("This is an invalid instance.")

    var resourceSplit = event.resources[0].split("/")
    var params = {
      InstanceIds: [resourceSplit[resourceSplit.length - 1]], // extract the last part of resource name as instance id
      DryRun: true
    };

    // call EC2 to stop the selected instances
    ec2.stopInstances(params, function(err, data) {
      if (err && err.code === 'DryRunOperation') {
        params.DryRun = false;
        ec2.stopInstances(params, function(err, data) {
          if (err) {
            callback(err, "fail");
          } else if (data) {
            console.log("Success", data.StoppingInstances);
            callback(null, "Success");
          }
        });
      } else {
        callback(err)
      }
    });
  } else {
    console.log("This is a good instance.")
    callback(null, "no action");
  }
};

このLambda関数はEC2インスタンスのタグをチェックします。EC2インスタンスが、必要なタグキーである”valid-key”が不足していたり”valid-value”を使っていなかったりすると、Lambda関数はEC2インスタンスを停止させます。実際のユースケースに合わせて、チェックのロジックと必要なタグを変更することができます。

Step2. IAM権限のセットアップ

“auto-stop-ec2-role”ロールにEC2インスタンスを停止するための権限を付与する必要があります。必要とされる最小権限は、ec2:StopInstancesです。新しいIAMポリシーを作成するため、 Use the New Visual Editor to Create and Modify Your AWS IAM Policiesを参照してください。EC2の特定のIAMポリシーを作成する際には、以下のページが参考になります。 Amazon EC2: EC2 インスタンスの起動または停止、およびセキュリティグループの変更を、プログラムによりコンソールで許可する

Step3. Lambda関数のテスト

Lambdaコンソールに戻ります。作成したLambda関数に対して、前述したサンプルイベントのJSONデータを用いて、”SampleTagChangeEventOnEC2”という名前のテストイベントを構成します。

[テスト]ボタンを押すと、CloudWatch Logsのコンソールに以下のエラーログが出力されます。これは、Lambda関数が正しくダミーのEC2インスタンスを停止しようとしたことを示します。

Step4. CloudWatchイベントルールの作成

さあ、Tag Change on Resourceイベントに適合し、作成したLambda関数をポイントするCloudWatchイベントルールを作成しましょう。CloudWatchイベントのコンソールにて、[ルールの作成]を選択し、以下のコードを貼り付けます。

{
  "source": [
    "aws.tag"
  ],
  "detail-type": [
    "Tag Change on Resource"
  ],
  "detail": {
    "service": [
      "ec2"
    ],
    "resource-type": [
      "instance"
    ]
  }
}

これは、EC2インスタンスに対する’Tag Change on Resource’イベントに適合するfine-grainedルールです。ターゲットとしてLambda関数を追加する必要があります。画面の右側で、先ほど作成したLambda関数である[AutoEC2Termination]を選択します。その後、[設定の詳細]をクリックします。

“ec2-instance-rule”という名前をルールに設定し、ルールを作成します。

Step5. Lambda関数を起動するためのCloudWatchイベントの権限付与

CLIを使用して、Lambda関数を起動するためのCloudWatchイベントの権限を付与します。以下のコマンドを実行します。

aws lambda add-permission --statement-id "TrustCWEToInvokeAutoEC2Termination" \
--action "lambda:InvokeFunction" \
--principal "events.amazonaws.com" \
--function-name "arn:aws:lambda:us-east-1:123456789012:function:AutoEC2Termination" \
--source-arn "arn:aws:events:us-east-1:123456789012:rule/ec2-instance-rule" \
--region us-east-1

Step6. 完成

foo:barというタグのEC2インスタンスを作成し最後のテストを行います。インスタンスは自動で停止し、CloudWatch Logsコンソール上で以下のようなログメッセージが出力されます。

Success [ { CurrentState: { Code: 64, Name: 'stopping' },
InstanceId: 'i-2222222222222',
PreviousState: { Code: 16, Name: 'running' } } ]

まとめ

この例では、EC2インスタンスのタグ変更に適合するCloudWatchイベントルールをどのように作成するかについて示しました。ルールでは、正しいタグが付与されていない場合にEC2インスタンスを自動的にシャットダウンするLambda関数を起動します。

Amazon CloudWatchイベントはAWSリソースのタグ変更をサポートしているため、多くのAWSサービスに渡ってイベントドリブンの自動化を構築できます。この新しい機能とLambdaの組み合わせは、AWSリソースにセキュアにアクセスし、オンデマンドでスケールし、コスト効率の高いサーバレスソリューションを構築するための一連のツールを提供します。

CloudWatchイベントの新しいTag Change on Resourceのユースケースとしては、他に以下のようなものが考えられます。

  • 通常と異なるIPアドレスからリソースアクセスされた際に警告を発する − タグを使用して、リソースにアクセスする各ユーザーのソースIPアドレスを格納します。タグが変更されるとCloudWatchイベントが生成され、ソースIPアドレスを有効なIPアドレスのリストと比較し、ソースIPアドレスが無効な場合は警告メールを送信します。
  • リソースのタグベースのアクセス制御に変更があったかどうかを監視する − タグに指定されたユーザーに基づいてリソースへのアクセスを設定した場合、タグの変更によって生成されたCloudWatchイベントを使用して、セキュリティチームによる監査を促すことができます。

あなたのアイデアや質問はAWS Tags developer forumにて歓迎いたします。

著者について

Qiutong SongはAWSのソフトウェアエンジニアです。プラットフォームチームの一員として、AWSを使用してお客様のペインを低減できるよう、非常にスケーラブルなシステムの構築を楽しんでいます。

 

 

 

飜訳はSA石橋が担当しました。原文はこちら