血と汗となみだを流す

個人の思ったこと、やったことの吐き出し口です。

Amazon S3 の PUT イベントを EventBridge -> Kinesis Data Firehose -> OpenSearch Service に入れてみる

Amazon S3 にオブジェクトを配置したときに発生する PUT イベントを OpenSearch Service に入れてみます。

Architecture

Amazon EventBridge の[ルール]-[イベントパターン]は以下です。

{
  "source": ["aws.s3"],
  "detail-type": ["Object Access Tier Changed", "Object ACL Updated", "Object Created", "Object Deleted", "Object Restore Completed", "Object Restore Expired", "Object Restore Initiated", "Object Storage Class Changed", "Object Tags Added", "Object Tags Deleted"],
  "detail": {
    "bucket": {
      "name": ["(バケット名)"]
    }
  }
}

ターゲットを Kinesis Data Firehose に指定します。
Kinesis Data Firehose のターゲットは OpenSearch Service を指定します。設定はすべてデフォルトです。
index 名は「kinesis」にしています。

S3 にオブジェクトを配置 (Object Created) したときに、OpenSearch Service に格納された PUT イベントデータは以下の形式でした。

{
        "_index" : "kinesis",
        "_id" : "49641493248204684799282029079614073971816170911334137858.0",
        "_score" : 1.0,
        "_source" : {
          "version" : "0",
          "id" : "062098df-c30a-c277-4d09-b16931dad59d",
          "detail-type" : "Object Created",
          "source" : "aws.s3",
          "account" : "999999999999",
          "time" : "2023-06-07T15:00:50Z",
          "region" : "us-east-1",
          "resources" : [
            "arn:aws:s3:::(バケット名)"
          ],
          "detail" : {
            "version" : "0",
            "bucket" : {
              "name" : "(バケット名)"
            },
            "object" : {
              "key" : "logs/yomple6.log",
              "size" : 202,
              "etag" : "3bde6fa2a35bca388769f10379523b26",
              "sequencer" : "0064809BA2121BBCA8"
            },
            "request-id" : "0FQ6PZCKNVCH78XD",
            "requester" : "999999999999",
            "source-ip-address" : "xxx.xxx.xxx.xxx",
            "reason" : "PutObject"
          }
        }
      }

ちなみに、PUT イベントから Lambda 関数をトリガーし出力した内容は以下でした。

{
  "Records": [{
        "eventVersion": "2.1",
        "eventSource": "aws:s3",
        "awsRegion": "us-east-1",
        "eventTime": "2023-06-07T02:15:25.358Z",
        "eventName": "ObjectCreated:Put",
        "userIdentity": {
            "principalId": "AWS:Axxxxxxxxxx"
        },
        "requestParameters": {
            "sourceIPAddress": "xxx.xxx.xxx.xxx"
        },
        "responseElements": {
            "x-amz-request-id": "ZN37J4JFE5YSXBKX",
            "x-amz-id-2": "QU+jgk1+c6TKKu9F3G2XDJL4VLhOgvV+Dg8ay7aMeEjKDN2lHfrR5TNeqDvqFgr/Mbm2AN8gEH4C89nPydRPSo2DR3qU0pZs"
        },
        "s3": {
            "s3SchemaVersion": "1.0",
            "configurationId": "a7c88a0e-e501-4910-b624-9312d2c6e5bf",
            "bucket": {
                "name": "(バケット名)",
                "ownerIdentity": {
                    "principalId": "A2YKLWBP9TAV5B"
                },
                "arn": "arn:aws:s3:::(バケット名)"
            },
            "object": {
                "key": "logs/sample.log",
                "size": 131,
                "eTag": "afa66f2c812defe614f69845dbea43a0",
                "sequencer": "00647FE83D4E98C147"
            }
        }
    }]
}

出力した Lambda (Python) の中身は以下です。

import json
from logging import getLogger, INFO

logger = getLogger(__name__)
logger.setLevel(INFO)

def lambda_handler(event, context):
    print("============ logger.info の出力 ============")
    logger.info(json.dumps(event))

    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello world",
        }),
    }

イベントデータの中身がどのようなデータ形式になるかの参考になればと思います。

Aurora MySQL のテーブルを Database Migration Service (DMS) → Kinesis Data Streams → Amazon Data Firehose (旧: Kinesis Data Firehose) → S3 でデータ出力してみた

以下の構成で Amazon Aurora MySQL 上のテーブルのデータを Amazon S3 にエクスポートします。

Architecture

Aurora MySQL 上のテーブルは以下のような形です。

use kajihirodb;
select * from dms_source_table;

id title keyword
1 風の谷のナウシカ ナウシカ
2 となりのトトロ トトロ
3 天空の城ラピュタ パズー
4 ハウルの歩く城 ハウル
5 千と千尋の神隠し 千尋

ここから DMS を利用してテーブルデータを取得し、Kinesis Data Streams に流します。
Kinesis Data Streams から Kinesis Data Firehose に送り、S3 に出力します。
Kinesis 関連の設定はすべてデフォルト値です。

以下、S3 に出力した結果です。

S3 Console

Kinesis Data Firehose で指定した S3 バケット上に yyyy / mm / dd で区切られ、その中にファイルが出力されています。
ファイルの中身は以下でした。

  • KDS-S3-KdgnY-1-2024-02-20-09-42-55-76b4ea85-b321-497a-b3b1-0e3d79b8d705
{
    "metadata": {
        "timestamp":    "2024-02-20T09:42:55.692040Z",
        "record-type":  "control",
        "operation":    "create-table",
        "partition-key-type":   "task-id",
        "schema-name":  "",
        "table-name":   "awsdms_apply_exceptions"
    }
}
  • KDS-S3-KdgnY-1-2024-02-20-09-42-56-7f7b4097-2208-4d6f-93f9-c8e5b8fc1b4a
{
    "metadata": {
        "timestamp":    "2024-02-20T09:42:56.340335Z",
        "record-type":  "control",
        "operation":    "drop-table",
        "partition-key-type":   "task-id",
        "schema-name":  "kajihirodb",
        "table-name":   "dms_source_table"
    }
}{
    "metadata": {
        "timestamp":    "2024-02-20T09:42:56.348950Z",
        "record-type":  "control",
        "operation":    "create-table",
        "partition-key-type":   "task-id",
        "schema-name":  "kajihirodb",
        "table-name":   "dms_source_table"
    }
}{
    "data": {
        "id":   1,
        "title":    "風の谷のナウシカ",
        "keyword":  "ナウシカ"
    },
    "metadata": {
        "timestamp":    "2024-02-20T09:42:56.360235Z",
        "record-type":  "data",
        "operation":    "load",
        "partition-key-type":   "primary-key",
        "schema-name":  "kajihirodb",
        "table-name":   "dms_source_table"
    }
}{
    "data": {
        "id":   2,
        "title":    "となりのトトロ",
        "keyword":  "トトロ"
    },
    "metadata": {
        "timestamp":    "2024-02-20T09:42:56.368645Z",
        "record-type":  "data",
        "operation":    "load",
        "partition-key-type":   "primary-key",
        "schema-name":  "kajihirodb",
        "table-name":   "dms_source_table"
    }
}{
    "data": {
        "id":   3,
        "title":    "天空の城ラピュタ",
        "keyword":  "パズー"
    },
    "metadata": {
        "timestamp":    "2024-02-20T09:42:56.376638Z",
        "record-type":  "data",
        "operation":    "load",
        "partition-key-type":   "primary-key",
        "schema-name":  "kajihirodb",
        "table-name":   "dms_source_table"
    }
}{
    "data": {
        "id":   5,
        "title":    "千と千尋の神隠し",
        "keyword":  "千尋"
    },
    "metadata": {
        "timestamp":    "2024-02-20T09:42:56.394266Z",
        "record-type":  "data",
        "operation":    "load",
        "partition-key-type":   "primary-key",
        "schema-name":  "kajihirodb",
        "table-name":   "dms_source_table"
    }
}
  • KDS-S3-KdgnY-1-2024-02-20-09-42-56-eb681b7d-0113-4e51-a1b7-b7670fdef71c
{
    "data": {
        "id":   4,
        "title":    "ハウルの歩く城",
        "keyword":  "ハウル"
    },
    "metadata": {
        "timestamp":    "2024-02-20T09:42:56.385582Z",
        "record-type":  "data",
        "operation":    "load",
        "partition-key-type":   "primary-key",
        "schema-name":  "kajihirodb",
        "table-name":   "dms_source_table"
    }
}

実際に S3 に出力した場合にどのようなデータ形式になるかの参考になればと思います。

API Gateway で統合レスポンスが設定できない場合

docs.aws.amazon.com

このタイプの統合は、Lambda プロキシ統合とも呼ばれ、お客様が統合リクエストまたは統合レスポンスを設定することはありません。

Lambda プロキシ統合(AWS_PROXY)になっていると、統合レスポンスの設定はできない。 クライアントと統合 Lambda 関数との間の直接的なやり取りに依存する。

Amazon ECS Exec を実行するための準備

公式ドキュメント

docs.aws.amazon.com

  • 前提条件を確認する

  • ECS サービスの enableExecuteCommandtrue (デフォルト false) にした後に起動したタスクから有効化される

  • enableExecuteCommand を有効化

aws ecs update-service \
    --cluster [クラスター名] \
    --enable-execute-command \
    --service [サービス名] 
aws ecs describe-tasks \
  --cluster [クラスター名] \
  --tasks [タスク ID] \
  | grep enableExecuteCommand

"enableExecuteCommand": true となっていれば OK

  • ECS Exec の実行
aws ecs execute-command \
    --cluster [クラスター名] \
    --task [タスクID] \
    --container [コンテナ名] \
    --interactive \
    --command [コマンド]

Fargate Spot キャパシティーが使用できない場合、Fargate へのフェイルオーバーはありますか?

aws.amazon.com

Fargate Spot キャパシティーが使用できない場合、Fargate へのフェイルオーバーはありますか?

利用可能な FARGATE_SPOT キャパシティーがない場合、FARGATE にフェイルバックするメカニズムを設定することはできません。

FARGATE_SPOT キャパシティーが使用できない場合、タスクはどうなりますか?

キャパシティーが使用できないために ECS スケジューラがタスクを起動できない場合、SERVICE_TASK_PLACEMENT_FAILURE イベントが発せられます。タスクは PROVISIONING の第 1 段階には到達せず、ECS イベントに通知も表示されません。ECS スケジューラは、引き続きタスクの起動を試行します。キャパシティーが使用可能になると、SERVICE_STEADY_STATE イベントが発せられます。

OpenSearch Service の Reserved Instance (RI) の柔軟性

docs.aws.amazon.com

RI は柔軟ではなく、予約したインスタンスタイプにのみ適用されます。
例えば、8 個の c5.2xlarge.search インスタンスのための予約は、16 個の c5.xlarge.search インスタンスまたは 4 個の c5.4xlarge.search インスタンスには適用されません。

JAWS-UG コンテナ支部 入門編 #6 コンテナの始め方 後編③(Trivyで脆弱性スキャン)

後編③とは

概要

  • ClairとTrivyをECSで動かして、dockerイメージの脆弱性をチェックする(今回はTrivy)
  • ハンズオン資料はGithubに公開されており、AWSアカウントがあれば誰でも実施することができます。ぜひ手を動かしてみることをお勧めします

資料のリンク

まえがき

Clairでは脆弱性なしと結果がでた envoyproxy/envoy-alpine:v1.10.0を Trivyで検査する

curl -s -X GET -H 'Content-Type:application/json' \
  "http://${API_HOST}:9000/api/v1/images/envoyproxy%2Fenvoy-alpine%3Av1.10.0/vulnerabilities" \
  | jq .
{
  "Count": 1,
  "Vulnerabilities": [
    {
      "Description": "ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input for every encryption operation. RFC 7539 specifies that the nonce value (IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length and front pads the nonce with 0 bytes if it is less than 12 bytes. However it also incorrectly allows a nonce to be set of up to 16 bytes. In this case only the last 12 bytes are significant and any additional leading bytes are ignored. It is a requirement of using this cipher that nonce values are unique. Messages encrypted using a reused nonce value are susceptible to serious confidentiality and integrity attacks. If an application changes the default nonce length to be longer than 12 bytes and then makes a change to the leading bytes of the nonce expecting the new value to be a new unique nonce then such an application could inadvertently encrypt messages with a reused nonce. Additionally the ignored bytes in a long nonce are not covered by the integrity guarantee of this cipher. Any application that relies on the integrity of these ignored leading bytes of a long nonce may be further affected. Any OpenSSL internal use of this cipher, including in SSL/TLS, is safe because no such use sets such a long nonce value. However user applications that use this cipher directly and set a non-default nonce length to be longer than 12 bytes may be vulnerable. OpenSSL versions 1.1.1 and 1.1.0 are affected by this issue. Due to the limited scope of affected deployments this has been assessed as low severity and therefore we are not creating new releases at this time. Fixed in OpenSSL 1.1.1c (Affected 1.1.1-1.1.1b). Fixed in OpenSSL 1.1.0k (Affected 1.1.0-1.1.0j).",
      "FixedVersion": "1.1.1b-r1",
      "InstalledVersion": "1.1.1a-r1",
      "PkgName": "openssl",
      "References": [
        "https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=ee22257b1418438ebaf54df98af4e24f494d1809",
        "https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=f426625b6ae9a7831010750490a5f0ad689c5ba3",
        "https://www.openssl.org/news/secadv/20190306.txt"
      ],
      "Severity": "MEDIUM",
      "Title": "openssl: ChaCha20-Poly1305 with long nonces",
      "VulnerabilityID": "CVE-2019-1543"
    }
  ]
}
docker run --rm \
  -e CLAIR_ADDR="http://${API_HOST}:6060" \
  supinf/klar:2.4 envoyproxy/envoy-alpine:v1.10.0 | jq .

{
  "LayerCount": 6,
  "Vulnerabilities": {}
}

Docker公式イメージであっても、古いバージョンには脆弱性が残っている例

  • python:3.7.3-alpine3.9python:3.4.10-alpine3.9
curl -s -X GET -H 'Content-Type:application/json' \
  "http://${API_HOST}:9000/api/v1/images/python%3A3.7.3-alpine3.9/vulnerabilities" \
  | jq .
{
  "Count": 2,
  "Vulnerabilities": [
    {
      "Description": "SQLite3 from 3.6.0 to and including 3.27.2 is vulnerable to heap out-of-bound read in the rtreenode() function when handling invalid rtree tables.",
      "FixedVersion": "3.28.0-r0",
      "InstalledVersion": "3.26.0-r3",
      "PkgName": "sqlite",
      "References": [
        "https://www.sqlite.org/releaselog/3_28_0.html",
        "https://www.sqlite.org/src/info/90acdbfce9c08858",
        "https://security.netapp.com/advisory/ntap-20190606-0002/",
        "https://usn.ubuntu.com/4004-1/",
        "https://usn.ubuntu.com/4004-2/"
      ],
      "Severity": "HIGH",
      "VulnerabilityID": "CVE-2019-8457"
    },
    {
      "Description": "An exploitable use after free vulnerability exists in the window function functionality of Sqlite3 3.26.0. A specially crafted SQL command can cause a use after free vulnerability, potentially resulting in remote code execution. An attacker can send a malicious SQL command to trigger this vulnerability.",
      "FixedVersion": "3.28.0-r0",
      "InstalledVersion": "3.26.0-r3",
      "PkgName": "sqlite",
      "References": [
        "http://packetstormsecurity.com/files/152809/Sqlite3-Window-Function-Remote-Code-Execution.html",
        "http://www.securityfocus.com/bid/108294",
        "https://security.netapp.com/advisory/ntap-20190521-0001/",
        "https://talosintelligence.com/vulnerability_reports/TALOS-2019-0777"
      ],
      "Severity": "MEDIUM",
      "VulnerabilityID": "CVE-2019-5018"
    }
  ]
}
curl -s -X GET -H 'Content-Type:application/json' \
  "http://${API_HOST}:9000/api/v1/images/python%3A3.4.10-alpine3.9/vulnerabilities" \
  | jq .
{
  "Count": 3,
  "Vulnerabilities": [
    {
      "Description": "ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input for every encryption operation. RFC 7539 specifies that the nonce value (IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length and front pads the nonce with 0 bytes if it is less than 12 bytes. However it also incorrectly allows a nonce to be set of up to 16 bytes. In this case only the last 12 bytes are significant and any additional leading bytes are ignored. It is a requirement of using this cipher that nonce values are unique. Messages encrypted using a reused nonce value are susceptible to serious confidentiality and integrity attacks. If an application changes the default nonce length to be longer than 12 bytes and then makes a change to the leading bytes of the nonce expecting the new value to be a new unique nonce then such an application could inadvertently encrypt messages with a reused nonce. Additionally the ignored bytes in a long nonce are not covered by the integrity guarantee of this cipher. Any application that relies on the integrity of these ignored leading bytes of a long nonce may be further affected. Any OpenSSL internal use of this cipher, including in SSL/TLS, is safe because no such use sets such a long nonce value. However user applications that use this cipher directly and set a non-default nonce length to be longer than 12 bytes may be vulnerable. OpenSSL versions 1.1.1 and 1.1.0 are affected by this issue. Due to the limited scope of affected deployments this has been assessed as low severity and therefore we are not creating new releases at this time. Fixed in OpenSSL 1.1.1c (Affected 1.1.1-1.1.1b). Fixed in OpenSSL 1.1.0k (Affected 1.1.0-1.1.0j).",
      "FixedVersion": "1.1.1b-r1",
      "InstalledVersion": "1.1.1a-r1",
      "PkgName": "openssl",
      "References": [
        "https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=ee22257b1418438ebaf54df98af4e24f494d1809",
        "https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=f426625b6ae9a7831010750490a5f0ad689c5ba3",
        "https://www.openssl.org/news/secadv/20190306.txt"
      ],
      "Severity": "MEDIUM",
      "Title": "openssl: ChaCha20-Poly1305 with long nonces",
      "VulnerabilityID": "CVE-2019-1543"
    },
    {
      "Description": "SQLite3 from 3.6.0 to and including 3.27.2 is vulnerable to heap out-of-bound read in the rtreenode() function when handling invalid rtree tables.",
      "FixedVersion": "3.28.0-r0",
      "InstalledVersion": "3.26.0-r3",
      "PkgName": "sqlite",
      "References": [
        "https://security.netapp.com/advisory/ntap-20190606-0002/",
        "https://usn.ubuntu.com/4004-1/",
        "https://usn.ubuntu.com/4004-2/",
        "https://www.sqlite.org/releaselog/3_28_0.html",
        "https://www.sqlite.org/src/info/90acdbfce9c08858"
      ],
      "Severity": "HIGH",
      "VulnerabilityID": "CVE-2019-8457"
    },
    {
      "Description": "An exploitable use after free vulnerability exists in the window function functionality of Sqlite3 3.26.0. A specially crafted SQL command can cause a use after free vulnerability, potentially resulting in remote code execution. An attacker can send a malicious SQL command to trigger this vulnerability.",
      "FixedVersion": "3.28.0-r0",
      "InstalledVersion": "3.26.0-r3",
      "PkgName": "sqlite",
      "References": [
        "http://packetstormsecurity.com/files/152809/Sqlite3-Window-Function-Remote-Code-Execution.html",
        "http://www.securityfocus.com/bid/108294",
        "https://security.netapp.com/advisory/ntap-20190521-0001/",
        "https://talosintelligence.com/vulnerability_reports/TALOS-2019-0777"
      ],
      "Severity": "MEDIUM",
      "VulnerabilityID": "CVE-2019-5018"
    }
  ]
}
  • python:3.7.3-alpine3.9で検出された脆弱性
    • CVE-2019-8457
    • CVE-2019-5018
  • python:3.4.10-alpine3.9で検出された脆弱性
    • CVE-2019-1543
    • CVE-2019-8457
    • CVE-2019-5018
  • CVE-2019-8457CVE-2019-5018に関しては2019/05に出ているやつなので両方で検出されているのかな
  • おそらくここのハンズオンで差を出したかったのはCVE-2019-1543
  • python:3.8.0b1-alpine3.9にしたらゼロ件でした
curl -s -X GET -H 'Content-Type:application/json' \
  "http://${API_HOST}:9000/api/v1/images/python%3A3.8.0b1-alpine3.9/vulnerabilities" \
  | jq .
{
  "Count": 0,
  "Vulnerabilities": []
}

CIにおけるリリース判定

  • CI中に脆弱性が出たらリリースを停止したい
  • exit codeや応答値を見て処理が停止するように書くことができる
docker run --rm \
      -e CLAIR_ADDR="http://${API_HOST}:6060" \
      supinf/klar:2.4 envoyproxy/envoy:v1.10.0 \
      | jq ".Vulnerabilities | length"
1
curl -s -X GET -H 'Content-Type:application/json' \
  "http://${API_HOST}:9000/api/v1/images/python%3A3.4.10-alpine3.9/vulnerabilities?skip-update=yes" \
  | jq -r ".Count"
3

まとめ

  • 「このツールならすべての脆弱性をチェックできる」というのは無さそう
  • Dockerイメージごとに得意分野が異なってる
  • 公式イメージの最新であっても脆弱性が入っている可能性がままある

感想

  • まだDockerfileを書くのもままならない状態なので、脆弱性というところまで頭が回っていない
  • しかしインターネットに公開するのであれば脆弱性チェックはしっかりやって置かないと行けないと感じた
  • ただ、そのリリースサイクルに追いついていけるかが自信ない・・・

終わりに

  • アウトプットにだいぶ時間が掛かってしまいましたが、ハンズオンの裏には膨大な情報があることがよくわかりました。
  • 噛めば噛むほど味がでる、とてもよいコンテンツです。
  • 次回も是非参加したいですね!抽選漏れてもハンズオンはやるぞ!!!
プライバシーポリシー