AWSの部屋

AWS学習者向けのブログです

スポンサーリンク

EventBridge を使用して EC2 インスタンスの停止を検知し再起動させる

はじめに

システム運用時に何かしらのイベントをきっかけに特定の処理を実行したり、スケジュールされた処理を実行したいことがあると思いますが、そういった際には EventBridge を使うと便利です。

Amazon EventBridge とは

AWSサービス、カスタムアプリケーション、 SaaSアプリケーションのための サーバレスイベントバスサービスで、多数のAWS サービスとSaaS アプリケーションを接続します。

イベントバスとは

イベントを受信するパイプライン

アーキテクチャ

ユーザが誤って EC2 インスタンスを停止したと仮定して、そのインスタンスを再起動させる処理を実行します。

イベント種類 内容
EventBridgeに直接送信されるイベント AWSリソースの状態変化を起点にイベントが発生する
CloudTrail経由で送信されるイベント ユーザーのAWSリソースに対する操作(=API呼び出し)を 起点にイベントが発生する
EventBridgeで未サポートのサービス

AWSのリソースの操作ログ を取得する AWS CloudTrail 経由でイベントを取得することが可能です。

手順

  1. EC2インスタンスの起動
  2. IAMロールの作成
  3. Lambda 関数の作成
  4. EventBridge ルールの作成
  5. 動作確認

1. EC2インスタンスの起動

EC2 インスタンスを起動させます。

2. IAMロールの作成

「AmazonEC2FullAccess」ポリシーを付与した「Lambda-Execute-Instance」ロールを作成します。これで Lambda から EC2 へのアクセスができるようになります。

3. Lambda 関数の作成

以下のように Lambda 関数を作成します。

[関数名]:MyFunctionEC2
[ランタイム]:Python 3.9
[既存のロール]:Lambda-Execute-Instance

EC2 インスタンスを開始する処理を実装します。

iimport boto3
import os

# インスタンスID
instances = [os.environ['INSTANCE_ID']]

def lambda_handler(event, context):
    ec2 = boto3.client('ec2', region_name='ap-northeast-1')
    
    # インスタンスの状態変化を取得
    action = event["Action"]
    
    # インスタンスの状態を取得
    response = ec2.describe_instances(InstanceIds=instances)
    ec2_status = response['Reservations'][0]['Instances'][0]['State']['Name']

    # インスタンスが停止されたかを判定
    if action == "Stop":
        ec2.start_instances(InstanceIds=instances)
        print('インスタンスを開始: ' + str(instances[0]))
    else:
        print('インスタンスに対する処理を実行しない')

デプロイが完了したら環境変数を設定します。

キー
INSTANCE_ID EC2 インスタンスの ID

4. EventBridge ルールの作成

少し長いですが、以下のように EventBridge ルールを作成します。

以下の JSON を Lambda に送信します。

Lambda のトリガーとして EventBridge が登録されました。

5. 動作確認

インスタンスの停止

インスタンスを停止します。

インスタンスの開始

インスタンスの停止後に自動的にインスタンスが開始されました。

さいごに

EventBridge を使うことによって簡単に EC2 インスタンスの状態変化を検知することができることがわかりました。AWS認定試験に必ず出題される EventBridge ですが、他にも様々なことができるので今度は他の機能も使ってみようと思います。

S3 に保存した CloudTrail のログを Athena で参照してみる

はじめに

CloudTrail を使うことによって「いつ」「誰が」「何を」実行したのかをログとして残すことができます。今回は CloudTrail で残したログを Athena で参照してみようと思います。

使用するサービス

サービス名 内容
Amazon S3 AWS が提供するオブジェクトストレージサービス
AWS CloudTrail AWS アカウントのガバナンス、コンプライアンス、運用監査、リスク監査を行うためのサービス
Amazon Athena Amazon S3 内のデータを SQL 分析できるインタラクティブなクエリサービス

アーキテクチャ

手順

  1. CloudTrail で証跡の作成
  2. S3 でログの確認
  3. Athena でテーブルの作成
  4. Athena でクエリの実行

1. CloudTrail で証跡の作成

以下のように設定し、証跡の作成を行います。

これで S3 に対するすべてのイベントをログに記録することができるようになります。

2. S3 でログの確認

「20220810-test-bucketバケットを作成し、その中に「hane.jpg」をアップロードしました。

このようにバケットにログが格納されました。

ログを確認すると作成したバケットに関するログが残っていることがわかります。

3. Athena でテーブルの作成

CloudTrail コンソールから「Athena テーブルを作成」をクリックします。

ログが格納されるバケットを選択しテーブルを作成します。

Athena のクエリエディタでテーブルが作成されていることを確認します。

4. Athena でクエリの実行

Athena でクエリを実行しログを参照します。以下はサンプルとして10行だけデータを抽出しています。

select eventTime as "イベント時間",
       userIdentity.userName as "ユーザー名",
       eventName as "イベント名",
       eventSource as "イベントソース"
  from "default"."cloudtrail_logs_aws_cloudtrail_logs_370560102364_44d0a6db"
 limit 10;

このように「いつ」「誰が」「何を」したのかを把握することができます。

また、以下のように対象のファイルに絞ってログを抽出することもできます。

select eventTime as "イベント時間",
       userIdentity.userName as "ユーザー名",
       eventName as "イベント名",
       eventSource as "イベントソース"
  from "default"."cloudtrail_logs_aws_cloudtrail_logs_370560102364_44d0a6db"
 where requestparameters like '%hane.jpg%' -- 検索対象のファイル名
 limit 10;

さいごに

まだ簡単な使い方だけですが、CloudTrail の基本的な使い方は理解することができました。今後は AWS認定ソリューションアーキテクト-プロフェッショナル試験に向けて理解を深めていこうと思います。

VPCエンドポイント経由で S3 にアクセスする

はじめに

EC2 から AWS サービスへの通信は、デフォルトではインターネットを経由したアクセスが必要になりますが、VPCエンドポイントを利用することで、AWS のデータセンター内のインターナルネットワーク経由でのアクセスが可能になります。今回はセキュアな通信方法として VPCエンドポイントを経由した S3 へのアクセスを試してみようと思います。

VPCエンドポイントとは

VPCAWS サービス間の接続を有効にするコンポーネントのことで、以下2つの種類の VPCエンドポイントがあります。本エントリーでは「ゲートウェイエンドポイント」を使います。

ゲートウェイエンドポイント

VPC のサービス専用のゲートウェイをアタッチします。ゲートウェイエンドポイントの対象サービスは S3 と DynamoDB です。

インターフェイスエンドポイント

VCP のサブネットに ENI を作成します。ENI に割り当てられたプライベートIPアドレスを使用してサービスにアクセスします(AWS PrivateLinkという技術を使用)。インターフェイスエンドポイントの対象サービスは S3を含み数多くあります。

アーキテクチャ

インターネット経由での S3 のアクセスを拒否し、VPCエンドポイント経由での S3 へのアクセスのみを許可します。

手順

  1. S3 バケットの作成
  2. IAMロールの作成
  3. EC2 インスタンスの起動
  4. VPCエンドポイントの作成
  5. バケットポリシーの設定
  6. 動作確認

1. S3 バケットの作成

「20220809-endpoint-gateway」というバケットを作成します。

適当にファイルもアップロードします。

2. IAMロールの作成

「EC2toS3」という EC2 が S3 へアクセスするための IAMロールを作成します。

3. EC2 インスタンスの起動

作成した IAMロールを設定し、プライベートサブネットに EC2 インスタンスを起動します。

また、パブリックサブネットにも同様に EC2 インスタンスを起動します。

4. VPCエンドポイントの作成

サービス「com.amazonaws.ap-northeast-1.s3」を選択します。

プライベートサブネットに属しているルートテーブルを選択してエンドポイントを作成します。

このようにエンドポイントが作成されます。

5. バケットポリシーの設定

バケットポリシーを以下のように設定し、VPCエンドポイントを経由した場合のみバケットへのアクセスを許可します。

{
  "Id": "VPCe",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VPCe",
      "Action": "s3:*",
      "Effect": "Deny",
      "Resource": "arn:aws:s3:::20220809-endpoint-gateway",
      "Condition": {
        "StringNotEquals": {
          "aws:SourceVpce": [
            "vpce-02d3065c3ea6a5612"
          ]
        }
      },
      "Principal": "*"
    }
  ]
}

6. 動作確認

インターネット経由でのアクセス

パブリックサブネットにあるインスタンスから S3 バケットにアクセスします。

aws s3 ls --region ap-northeast-1 --recursive s3://20220809-endpoint-gateway

アクセスが拒否されました。想定通りの動きですね。

VPCエンドポイント経由でのアクセス

プライベートサブネットにあるインスタンスから S3 バケットにアクセスします。

aws s3 ls --region ap-northeast-1 --recursive s3://20220809-endpoint-gateway

S3 バケットにアクセスすることができました。

さいごに

このように VPCエンドポイントを使うことでセキュアな通信が可能になります。インターフェイスエンドポイントについてはこちらのエントリーでまとめていますので、興味のある方はぜひ読んでみてください。

SQS キューのメッセージを Lambda で処理してみる

はじめに

前回のエントリーで S3 と SQS の連携を試してみました。本エントリーはその続きで SQS キューに S3 から通知がきた後に SQS キューのメッセージを Lambda で処理してみようと思います。

使用するサービス

  • Amazon S3・・・AWS が提供するオブジェクトストレージサービス
  • Amazon SQS・・・フルマネージド型のメッセージキューイングサービス
  • AWS Lambda・・・サーバーをプロビジョニングしたり管理しなくてもコードを実行できるコンピューティングサービス

アーキテクチャ

役割
  • Amazon S3・・・アップロードするファイルを格納
  • Amazon SQS・・・ S3 にアップロードされたファイルの情報を Lambda に送信
  • AWS Lambda・・・SQS から送信されたファイル情報をもとにファイルの名前を変えて S3 に同じファイルをアップロード

手順

  1. IAMロールを作成
  2. S3 バケットを作成
  3. SQS キュー を作成
  4. Lambda 関数を作成
  5. 動作確認

1. IAMロールを作成

「Lambda-SQS-Execution-Role」という名前のLambda に SQS と S3 に対する実行権限を付与するロールを作成します。

2. S3 バケットを作成

前回のエントリーを参照してください。

3. SQS キュー を作成

前回のエントリーを参照してください。

4. Lambda 関数を作成

SQS キューのメッセージを処理するLambda関数を作成します。

[関数名]:sqs-message-receive
[ランタイム]:Python 3.9
[実行ロール]:Lambda-SQS-Execution-Role

SQS キューをトリガーとして追加します。

ソースコード

S3 バケットにアップロードしたファイルの名前を変えて同じバケットにアップロードするプログラムです。

import json
import os
import urllib.parse
import boto3
import subprocess
from datetime import datetime

def lambda_handler(event, context):
    
    s3 = boto3.resource('s3')
    
    # バケット名取得
    bucket_name = event['Records'][0]['s3']['bucket']['name']
    
    # バケット取得
    bucket = s3.Bucket(bucket_name) 
    
    # アップロードしたファイル名を取得
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    
    # Lambdaのローカルのファイル保存先(/tmp)を設定
    file_path = '/tmp/' + datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
    
    try:
        # /tmpにダウンロード用のフォルダを作成
        cmd = ['mkdir', '-p', file_path]
        subprocess.run(cmd, stdout=subprocess.PIPE)
    
        # S3に格納したファイルを作成したフォルダにダウンロード
        bucket.download_file(key, os.path.join(file_path, key))   
    
        # ファイルの名前を変えてS3にPUT
        bucket.upload_file(os.path.join(file_path, key), 'hane2.jpg')
        
        return
    except Exception as e:
        print(e)

5. 動作確認

hane.jpg をアップロードします。

Lambdaによってhane2.jpg がバケットに作成されました。

さいごに

今回は簡単な処理だけだったので SQS を使う必要はないと思いますが、SQS と Lambda を実際にどのように連携するかを理解するためのいい勉強になりました。今度はデッドレターキューなど SQS をフルに活用できる構成を試してみたいですね。

S3 へのファイル格納時に SQS キューに通知をしてみる

はじめに

AWS認定試験に必ず出題される SQS ですが、今まで触ったことがなかったので本日は S3 と連携させて SQS を試してみたいと思います。

使用するサービス

  • Amazon S3・・・AWS が提供するオブジェクトストレージサービス
  • Amazon SQS・・・フルマネージド型のメッセージキューイングサービス

アーキテクチャ

手順

  1. S3 でバケットを作成
  2. SQS キューを作成
  3. S3 でイベント通知を作成
  4. 動作確認

1. S3 でバケットを作成

「20220807-sqs-test」というバケットを作成します。設定はデフォルトでOKです。

2. SQS キューを作成

「TestQueue」という SQS キューを作成します。

アクセスポリシーを以下のように設定します。

{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__owner_statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "SQS:*",
      "Resource": "arn:aws:sqs:ap-northeast-1:xxxxxxxxxxxxx:TestQueue",
      "Condition": {
        "ArnLike": {
          "aws:SourceArn": "arn:aws:s3:*:*:20220807-sqs-test"
        }
      }
    }
  ]
}

3. S3 でイベント通知を作成

イベント名とイベントタイプを設定し、作成した SQS キューを設定して「変更の保存」をクリックします。

4. 動作確認

バケットにファイルをアップロードします。

「メッセージを送受信」をクリックします。

「メッセージをポーリング」をクリックします。

メッセージが2件表示されます。

上のキューのメッセージ

アップロードしたファイルの情報などが記載されています。

{"Records":[{"eventVersion":"2.1","eventSource":"aws:s3","awsRegion":"ap-northeast-1","eventTime":"2022-08-07T14:33:59.870Z","eventName":"ObjectCreated:Put","userIdentity":{"principalId":"AWS:AIDAVMRY2N7OKTN33RYNV"},"requestParameters":{"sourceIPAddress":"60.95.0.122"},"responseElements":{"x-amz-request-id":"Q73VJ1CPJ64CKJQ0","x-amz-id-2":"jqP4VGy4ubSEOvB+XRCdTjWUJEuCkkWRyiRlxdKCNqjP8cTjRUg0JGhDYsW9RprSsQPqdnlOviWD11mpmynwSJzlRyzzT8rgCka5XEnLzq8="},"s3":{"s3SchemaVersion":"1.0","configurationId":"SQS-Event","bucket":{"name":"20220807-sqs-test","ownerIdentity":{"principalId":"A2B5KBXGR14B9R"},"arn":"arn:aws:s3:::20220807-sqs-test"},"object":{"key":"hane.jpg","size":9846,"eTag":"ad1cdeed43375dca5b5e892be0968525","sequencer":"0062EFCD57CFFC5419"}}}]}
下のキューのメッセージ

こちらは S3 からの通知など概要レベルの情報が記載されています。

{"Service":"Amazon S3","Event":"s3:TestEvent","Time":"2022-08-07T14:33:31.875Z","Bucket":"20220807-sqs-test","RequestId":"0D8YVTX0QRFW78X3","HostId":"xj8sYZZALIXycdCYK54KnulIng2R3MMjMqjMAMM3gCQ5UqsHcL46nXX3FZ8x/Wpg4Duwz1IHXGY="}

さいごに

はじめて SQS を使用してみましたが設定は簡単にできました。何となく理解していたものが実際にサービスを使用することで理解が深まった気がします。次は SQS と Lambda の連携を試してみようと思います。

CloudFront の署名付きURL を使ったコンテンツの配信方法

はじめに

S3 にあるファイルを特定のユーザーに限定して配信したい場合などがあるかと思いますが、その際、署名付きURL が役に立ちます。S3 と署名付きURLだけでも実現可能なのですが、本エントリーではよりセキュアな配信を可能にするために CloudFront も使ってみようと思います。

署名付きURLとは

アクセスを許可したいオブジェクトに対して期限を指定して URL を発行する機能です。バケットやオブジェクトのアクセス制御を変更することなく特定のオブジェクトに一時的にアクセスを許可したい場合に非常に有効です。

使用するサービス

アーキテクチャ

実際に運用する際は上記のようになるのが一般的かと思いますが、今回は EC2 は使用せずに署名付きURLをローカルで作成します。

手順

  1. S3 バケットにファイルをアップロード
  2. ローカルで公開鍵・秘密鍵を作成
  3. 公開鍵を CloudFront に登録
  4. キーグループを CloudFront に 作成
  5. CloudFrontディストリビューションを作成
  6. 署名付きURLの生成
  7. 動作確認

1. S3 バケットにファイルをアップロード

以下のように画像をアップロードしました。

アップロードした画像はこちらです。

2. ローカルで公開鍵・秘密鍵を作成

署名付き URL を生成するためには公開鍵・秘密鍵を作成する必要があります。OpenSSL を使用して作成してみます。

まずは秘密鍵を作成します。

openssl genrsa -out private_key_presigned_url.pem 2048

秘密鍵から、CloudFront に登録するための公開鍵を作成します。

openssl rsa -pubout -in private_key_presigned_url.pem -out public_key_presigned_url.pem

作成完了です。

3. 公開鍵を CloudFront に登録

「パブリックキーを作成」をクリックします。

「名前」と「キー」を入力して「パブリックキーを作成」をクリックします。「キー」に入力する値は以下のコマンドで取得します。

cat public_key_presigned_url.pem | pbcopy

4. キーグループを CloudFront に 作成

「キーグループを作成」をクリックします。

登録した公開鍵を設定し、「キーグループを作成」をクリックします。

5. CloudFrontディストリビューションを作成

ディストリビューションを作成」をクリックします。

「オリジンドメイン」に作成した S3 バケット、「S3バケットアクセス」で「はい、OAIを使用します」を選択します。

「ビューワーのアクセスを制限する」で「Yes」を選択、作成したキーグループを設定してデゥストリビューションを作成をクリックします。

6. 署名付きURLの生成

AWS CLI を使って CloudFront の署名付き URL を生成します。詳細はこちらを参照してください。

aws cloudfront sign \
--url https://d3pmk7agw3wwym.cloudfront.net/hane.jpg \
--key-pair-id xxxxxxxxx \
--private-key private_key_presigned_url.pem \
--date-less-than 2022-08-07T08:30:00+09:00

以下のように署名付きURLが生成されました。

https://d3pmk7agw3wwym.cloudfront.net/hane.jpg?Expires=1659828600&Signature=zJkStrKGj-pciCgh-vOyaMnD6zDMXvsalGA0PPGh2IdoHXyFX-
~中略~
rQKarrjBT3OymyWJDBZrjL6oJDORU2v1v94aDdeIukeXyIVqbyeZ8N7Py0aZznXVI16qsgtPHqzTx~OZXgOEYgrJRR73DzF08YbT3TTNUSGo70gMwMLzXKsCq0VWRWxE5PNZTZ1-ULaL3A__&Key-Pair-Id=xxxxxxxx

7. 動作確認

署名付きURLでアクセス

S3バケットに格納されている画像にアクセスすることができました。

通常URLでアクセス

アクセスできないことがわかりました。

署名付き URL の有効期限が切れた後に署名付きURLでアクセス

アクセスできないことがわかりました。

さいごに

AWS認定試験には必ずと言っていいほど出題される署名付きURLに関して何となく理解していたつもりでしたが、実際に自分で使い方を試してみることでより理解が深まった気がします。やはり座学ではなく実践で学ぶのが一番ですね。

SAML による AWS へのシングルサインオン

はじめに

AWS アカウントに IAM ユーザーを作成しログインする代わりに、ID プロバイダー(IdP)を使⽤しシングルサインオンすることができます。これは、組織に独⾃のID 基盤がある場合や、複数の AWS アカウントを使⽤している場合に便利です。今回は AWS 認定ソリューションアーキテクト - プロフェッショナル試験に向けて、SAML を使った AWS へのシングルサインオンに挑戦してみようと思います。

シングルサインオンとは

1度のユーザー認証によって複数のシステム(業務アプリケーションやクラウドサービスなど)の利用が可能になる仕組みを指します。

シングルサインオンに必要な要素

要素 説明 本エントリーで活用するサービス
アイデンティティストア IDプロバイダー(IdP)のユーザ管理 GMOトラスト・ログイン
IDプロバイダー(IdP) ユーザー・アカウントを管理するサービス GMOトラスト・ログイン
サービスプロバイダー なんらかのサービスを提供する企業または組織 AWS

AWSにおけるシングルサインオンのイメージ

手順

  1. IDプロバイダーの設定1
  2. サービスプロバイダーの設定
  3. IAM ロールの作成
  4. IDプロバイダーの設定2
  5. アイデンティティストアのユーザの作成
  6. 動作確認

1. IDプロバイダーの設定1

アカウントの登録後、ID プロバイダー情報のメタデータをダウンロードします。アプリの登録はせずにこのまま次の手順に進みます。

管理者画面に遷移します。

アプリの追加ボタンを押します。

AWS IAM(SAML) をクリックします。

ID プロバイダー情報のメタデータをダウンロードします。

2. サービスプロバイダーの設定

IAM管理画面で「プロバイダを追加」をクリックします。

前工程でダウンロードしたメタデータを選択し、プロバイダーの追加をします。

プロバイダのARNを控えておきます。

3. IAM ロールの作成

先ほど作成したプロバイダを選択し、以下のようにロールを作成します(アタッチするポリシーやロール名は適当でOK)。

ロールの ARN を控えておきます。

4. IDプロバイダーの設定2

「サービスプロバイダーの設定」の「SAML属性の設定」に控えておいた「ロールの ARN」と「プロバイダの ARN」を「,」で区切った「ロールのARN,プロバイダのARN」の形式で入力し、アプリの登録を行います。

例:arn:aws:iam::000000000000:role/saml-role, arn:aws:iam::000000000000:saml-provider/sanvarie_test

5. アイデンティティストアのユーザの作成

このようにユーザを二つ作成しました。

6. 動作確認

ログインができている場合、画面の上部にロール名/ユーザー名@アカウントIDが表記されます。

一人目のユーザでログイン

二人目のユーザでログイン

さいごに

何となくでしかシングルサインオンの仕組みを理解していなかったのですが、実現に必要なものを整理し実際に手を動かすことによって理解が深まった気がします。次回は OpenID Connect を使ったシングルサインオンにも挑戦してみようと思います。