yuj1osm's tech blog

クラウドやセキュリティなど

AWS Systems ManagerのAutomationとChange Calendarが統合されました

AWS Systems Manager AutomationとAWS Systems Manager Change Calendarが統合されました。
これにより、カレンダーで指定した期間のみAutomationの実行を許可/拒否できるようになるので、検証してみました。

アップデート概要

  • AWS Systems Manager AutomationとAWS Systems Manager Change Calendarが統合された
  • これまでは、ドキュメントでカレンダーをチェックする処理をユーザが実装する必要があったが、今回のアップデートでオートメーションとカレンダーを関連付けることで、ユーザが実装することなく手軽に統合できるようになった

aws.amazon.com

オートメーションを実行する

統合前にAutomationを実行して挙動を確認します。
テスト用のEC2インスタンスを用意します。

AWS Systems Manager」→「オートメーション」→「オートメーションの実行」を押下します。

EC2インスタンスを再起動するドキュメント「AWS-RestartEC2Instance」が標準で用意されているので、今回はそれを使用します。
入力パラメータで用意したEC2インスタンスを選択して実行します。

しばらく待つと実行が完了します。

カレンダーを設定する

それでは、カレンダーを設定して先ほどの手順を実行してみます。
「オートメーション」→「設定」→「設定」を押下します。

「Turn on Change Calendar integration」にチェックを入れます。

「Create Change Calender」を押下します。

今回は、カレンダータイプを「デフォルトで開く」にして作成します。

カレンダータイプは以下の違いがあるので、要件に応じて設定するとよいです。

  • 「デフォルトで開く」はイベント期間中は実行を拒否
     例えば、メンテナンスやリリース作業の時間帯は実行拒否したい場合に、拒否する時間帯をイベントとして登録
  • 「デフォルトで閉じる」はイベント期間中のみ実行を許可
     例えば、実行頻度が低く限られた時間帯に実行許可したい場合に、許可する時間帯をイベントとして登録

カレンダーが作成できたので、イベントを作成してみます。

今回のカレンダータイプは「デフォルトで開く」なので、イベントスケジュールの時間帯は実行を拒否できます。

イベントが作成されました。

オートメーションの画面で作成したカレンダーを選択し、保存します。

オートメーションの実行拒否を確認

先ほどオートメーションを実行した手順で、「AWS-RestartEC2Instance」を実行してみます。
すると、「Cannot Start Automation Execution because calendar(test-calender) is in CLOSED state」と表示され実行が拒否されました。

Change Managerの実行拒否を確認

AWS Systems ManagerにはChange Managerという機能があり、オートメーションに承認機能を追加したものです。
このChange Managerも同様に実行拒否されるのか確認します。

Change Managerテンプレートを作成します。
ランブックは「AWS-RestartEC2Instance」を指定します。
このテンプレートでリクエストを作成します。

ランブックのパラメータは、テスト用のEC2インスタンスを選択します。

リクエストを作成しました。

指定した承認者の画面で、「承認」を押下します。

ステータスが「完了 (エラーあり)」と表示されています。

詳細を確認すると、「Failed to start runbook due to: Cannot Start Automation Execution because calendar(test-calender) is in CLOSED state」と表示され実行が拒否されました。

まとめ

オートメーションやChange Managerは便利ですが、メンテナンスやリリース作業時には実行して欲しくない要件があると思います。
これまでは、ドキュメントでカレンダーをチェックする処理をユーザが実装する必要がありましたが、今回のアップデートで手軽に統合ができるようになりました。
本番環境に対するリスク低減や内部統制の観点でも、非常に使い勝手が良い機能だと思います。

AWS Security Hubのコントロールをワンライナーで一括無効化する

AWS Security Hubのコントロールは、必要に応じて無効化すると管理がしやすいです。
しかしながら、AWSマネジメントコンソールからAWS Security Hubのコントロールを一括無効化できません。
そこで、AWS Security Hubのコントロールワンライナーで一括無効化してみます。

コントロールを手動で無効化する

まずは手動で無効化してみます。
セキュリティ基準から任意のコントロールを選択します。

「コントロールの無効化」を押下します。

無効化する理由を記載して、「無効化」を押下します。

無効化されました。

しかしながら、AWSマネジメントコンソールからAWS Security Hubのコントロールを一括無効化できません。
そのため、複数のコントロールを無効化する際は、先ほどの手順で1つずつ無効化する必要がありますが、時間がかかりミスの原因にもなります。

コントロールワンライナーで一括無効化する

今度は、ワンライナーで一括無効化してみます。
コマンドの入力方法はいろいろありますが、今回はAWS CloudShellを使います。

今回は、「AWS 基礎セキュリティのベストプラクティス v1.0.0」のAPIGateway関連を一括無効化してみます。
以下のコマンドを実行します。
※コマンド冒頭のは自身のAWSアカウントIDに置き換えてください。

awsAccountId=<awsAccountId>; for arn in $(aws securityhub describe-standards-controls --standards-subscription-arn "arn:aws:securityhub:ap-northeast-1:$awsAccountId:subscription/aws-foundational-security-best-practices/v/1.0.0" --query "Controls[].[StandardsControlArn]" --output text); do if [[ "$arn" =~ "APIGateway" ]]; then aws securityhub update-standards-control --control-status "DISABLED" --disabled-reason "監視不要のため" --standards-control-arn "$arn"; echo "$arn is Disabled"; else :; fi; done

以下が実行結果です。
※出力結果のは、コマンド冒頭ので入力したAWSアカウントIDが入ります。

$ awsAccountId=<awsAccountId>; for arn in $(aws securityhub describe-standards-controls --standards-subscription-arn "arn:aws:securityhub:ap-northeast-1:$awsAccountId:subscription/aws-foundational-security-best-practices/v/1.0.0" --query "Controls[].[StandardsControlArn]" --output text); do if [[ "$arn" =~ "APIGateway" ]]; then aws securityhub update-standards-control --control-status "DISABLED" --disabled-reason "監視不要のため" --standards-control-arn "$arn"; echo "$arn is Disabled"; else :; fi; done
arn:aws:securityhub:ap-northeast-1:<awsAccountId>:control/aws-foundational-security-best-practices/v/1.0.0/APIGateway.1 is Disabled
arn:aws:securityhub:ap-northeast-1:<awsAccountId>:control/aws-foundational-security-best-practices/v/1.0.0/APIGateway.2 is Disabled
arn:aws:securityhub:ap-northeast-1:<awsAccountId>:control/aws-foundational-security-best-practices/v/1.0.0/APIGateway.3 is Disabled
arn:aws:securityhub:ap-northeast-1:<awsAccountId>:control/aws-foundational-security-best-practices/v/1.0.0/APIGateway.4 is Disabled
arn:aws:securityhub:ap-northeast-1:<awsAccountId>:control/aws-foundational-security-best-practices/v/1.0.0/APIGateway.5 is Disabled
arn:aws:securityhub:ap-northeast-1:<awsAccountId>:control/aws-foundational-security-best-practices/v/1.0.0/APIGateway.8 is Disabled
arn:aws:securityhub:ap-northeast-1:<awsAccountId>:control/aws-foundational-security-best-practices/v/1.0.0/APIGateway.9 is Disabled

APIGateway関連のコントロールをいくつか見てみると、無効化されていることが確認できます。

まとめ

AWSマネジメントコンソールからAWS Security Hubのコントロールを一括無効化できません。
CLIからAPI経由で無効化できるので、必要に応じて一括無効化できるようなコマンドを用意しておくと便利です。

goofysを使用したAmazon Linux2へのS3マウント

S3バケット内のオブジェクトを、CLIで手軽に操作したい時があると思います。
今回は、goofysを使用したAmazon Linux2へのS3マウントを紹介します。

goofysとは

Goで記述されたツールで、S3バケットファイルシステムとしてマウントすることができます。

github.com

goofysをセットアップする

事前準備

マウントさせるS3バケットを作成し、テスト用のファイルをアップロードします。

マウントするEC2インスタンスを作成します。

インスタンスに付与するロールには、S3を読み込みできる権限を付けておきましょう。
読み込むだけでよいなら、「AmazonS3ReadOnlyAccess」を設定するとよいでしょう。

goofsyインストール

作成したインスタンスにログインし、以下のコマンドでgoofysをインストールします。

$ sudo yum -y update
$ sudo yum install -y golang fuse
$ sudo wget https://github.com/kahing/goofys/releases/download/v0.24.0/goofys -P /usr/local/bin/
$ sudo chmod 755 /usr/local/bin/goofys

S3をマウントする

マウントポイントを作成します。

$ sudo mkdir -m 755 test-goofys-s3

続いて、fstabに追記します。

$ sudo vim /etc/fstab

以下の形式で追記します。
今回は読み込み専用でマウントします。

/usr/local/bin/goofys#<バケット名> /S3/<マウントポイント> fuse _netdev,allow_other,--dir-mode=0755,--file-mode=0644,--uid=1001,--gid=0,ro 0 0

追記後は以下のようになります。

#
UUID=<uuid>     /           xfs    defaults,noatime  1   1
/usr/local/bin/goofys#test-goofys-s3 /mnt/test-goofys-s3 fuse _netdev,allow_other,--dir-mode=0755,--file-mode=0644,--uid=1001,--gid=0,ro 0 0

fstabに追記したら保存して、マウントします

$ sudo mount -a

mountコマンドやdfコマンドでマウントされていることを確認します。

$ mount
(省略)
/mnt/test-goofys-s3 on /mnt/test-goofys-s3 type fuse (ro,relatime,user_id=0,group_id=0,default_permissions,allow_other)
(省略)
$ df -h
(省略)
test-goofys-s3  1.0P     0  1.0P   0% /mnt/test-goofys-s3
(省略)

S3バケットのオブジェクトをCLIで確認できました。

$ ls /mnt/test-goofys-s3/
test.txt   test2.txt
$ cat /mnt/test-goofys-s3/test.txt
This is test document
$ cat /mnt/test-goofys-s3/test2.txt
This is test document2

まとめ

goofysを使用することで、S3マウントが簡単に実現できました。
CLIでオブジェクトの操作ができるようになるので、grepなどで検索することが可能になり、複雑な分析にも役立ちます。
ただし、goofysはAWSのサポート外なので、本番サービスに使用するのは控え、あくまで内部利用にとどめましょう。

AWS Storage Gatewayを使用してEC2 WindowsにS3バケットをクロスアカウントでドライブマウントする

AWS Storage Gatewayを使用して、EC2に構築したWindowsに、他アカウントのS3バケットをドライブマウントしてみました。

登場するリソースが多く設定も複雑なので、まずは今回作成する構成図を示します。

アカウントAにStorage Gatewayを立てて、アカウントBのWindowからStorage Gateway経由でS3をドライブマウントします。

AWS Storage Gatewayとは

AWS Storage Gateway は、オンプレミスにあるファイルサーバなどのストレージとAmazon S3の大容量ストレージを密接に連携させ、堅牢かつ可用性の高いストレージを構築することが可能になるサービスです。

aws.amazon.com

AWS Storage Gatewayの構築

構築はアカウントAでの作業です。

バケット作成

ドライブマウントするバケットを作成します。
バケット名:test-storagegw-bucket

セキュリティグループ作成

Storage Gatewayインスタンス用のセキュリティグループを作成します。
セキュリティグループ名:test-storagegw-sg
インバウンドルール:

S3エンドポイント用のセキュリティグループを作成します。
セキュリティグループ名:test-s3endpoint-sg
インバウンドルール:

  • 「アカウントA」のVPCのIP CIDR→HTTPS(443)

エンドポイント作成

Storage Gatewayを使用して、S3バケットとプライベート通信をするために、エンドポイントを作成します。
エンドポイント名:test-s3-ep
サービス:S3 Interface型

セキュリティグループは前述の「test-s3endpoint-sg」を選択します。

ゲートウェイ作成

Storage Gatewayから「ゲートウェイ」→「ゲートウェイの作成」を押下します。

ゲートウェイ名:test-storagegw-gw
ゲートウェイタイプ:Amazon S3 ファイルゲートウェイ

ホストプラットフォームに「Amazon EC2」を選択して、「設定をカスタマイズ」→「インスタンスの起動」を押下します。
ここでインスタンスの要件が記述されており、インスタンスタイプは「m5.xlarge」、EBSは追加で「150GiB」必要になります。

インスタンス作成

インスタンス作成の画面に遷移しますので、要件通りに作成しています。
インスタンス名:test-storagegw-ec2
インスタンスタイプ:m5.xlarge

後ほどSSHログインに必要なため、キーペアを作成しておきます。
ネットワークはパブリックに配置します。
パブリックIPの自動割り当ては、後ほどElastic IPを割り当てるため無効化しておきます。
セキュリティグループは最初に作成した、「test-storagegw-sg」を選択します。

ストレージはルートボリュームに加え、150GiBのEBSボリュームを追加します。

インスタンスが起動しました。

Elastic IPを割り当てます。

インスタンスにElastic IPが割り当てられていることを確認します。

ゲートウェイ作成(続き)

ゲートウェイ作成の画面に戻り、「ゲートウェイのセットアップの確認」にチェックを付け、次に進みます。

IPアドレスに「test-storagegw-eip」のIPアドレスを入力し、次に進みます。

設定を確認し、「次へ」を押下します。

ここまでの設定がうまくいくと、「ゲートウェイの設定」画面に遷移します。
「キャッシュストレージの設定」にてローカルディスクをロードしているので1分程度待ちます。

ロードが完了したら、「CloudWatchロググループ」と「CloudWatchアラーム」の作成を選択して、「設定」を押下します。

ゲートウェイが作成されました。

注意
ゲートウェイの設定」に遷移せず、以下のようなエラーが表示された場合は、設定が間違っている可能性があります。
よくある間違いとして、入力したIPアドレスやセキュリティグループの誤りがありますので、設定を確認してみましょう。

ファイル共有作成

Storage Gatewayの「ファイル共有」→「ファイル共有の作成」を押下します。

先ほど作成したゲートウェイ「test-storagegw-gw」を選択します。
バケットは最初に作成した「test-storagegw-bucket」を入力します。
「S3のVPCエンドポイントを使用」にチェックを付けて、最初に作成したVPCエンドポイントIDを選択します。

注意
エンドポイントのサービスがS3ではなかったり、インバウンドに443が許可されていない場合、以下のようなエラーが表示されますので、設定を確認してみましょう。

オブジェクトへのアクセスは「SMB」を選択します。
監査ログ用のロググループは作成します。

Storage Gatewayは、EBS→S3の場合は即時共有されますが、S3→EBSは即時共有されません。
そこで、「S3からのキャッシュの自動更新」で更新頻度を設定します。
ここではTTL5分とします。

ストレージ設定はデフォルトのままにします。

SMBの認証方法を「ゲストアクセス」にして、「ゲストパスワード」を設定します。

最後に設定を確認して、「作成」を押下します。

作成が完了するまで1分ほど待ちます。
ステータスが「更新中」→「使用不可」→「利用可能」と遷移します。
「使用不可」と表示されても焦らず待ってみましょう。

ファイル共有が作成されると、詳細画面からドライブマウントのコマンドを取得できるので、コピーしておきましょう。

ここで、ファイル共有の作成過程で作成されたロールも確認しておきましょう。
「StorageGatewayBucketAccessRole~」というサービスロールが作成されています。
Storage GatewayがS3との共有に必要な権限が設定されています。

許可

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:GetAccelerateConfiguration",
                "s3:GetBucketLocation",
                "s3:GetBucketVersioning",
                "s3:ListBucket",
                "s3:ListBucketVersions",
                "s3:ListBucketMultipartUploads"
            ],
            "Resource": "arn:aws:s3:::test-storagegw-bucket",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:DeleteObject",
                "s3:DeleteObjectVersion",
                "s3:GetObject",
                "s3:GetObjectAcl",
                "s3:GetObjectVersion",
                "s3:ListMultipartUploadParts",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::test-storagegw-bucket/*",
            "Effect": "Allow"
        }
    ]
}

信頼関係

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "storagegateway.amazonaws.com"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": “<accountID>",
                    "aws:SourceArn": "arn:aws:storagegateway:ap-northeast-1:“<accountID>:gateway/<gatewayID>"
                }
            }
        }
    ]
}

挙動の確認

ドライブマウント確認

アカウントBのEC2に立てたWindowからドライブマウントをしてみます。

このWindowはElastic IPを使ってインターネット通信を行います。

ファイル共有作成後にコピーしたコマンドを適切に変更して、Windowのコマンドプロンプトで実行します。

net use Z: \\<test-storagegw-eip>\test-storagegw-bucket /user:sgw-XXXXXXXX\smbguest

パスワードを聞かれるので、ファイル共有作成時に設定した、SMBの「ゲストパスワード」を入力します。
成功すると、「The command completed successfully.」と表示されます。

エクスプローラーを見ると、ZドライブにS3がマウントされていることを確認できました。

ファイル共有確認

WindowsでZドライブにファイルを作成します。

アカウントAのS3バケットを見ると、Windowsで作成されたファイルが反映されています。

次に、アカウントAのS3バケットにファイルを作成します。

しばらく待つと、WindowsのZドライブにファイルが反映されています。
ファイル共有作成時のTTLの設定どおり、最大5分の遅延があります。

CloudWatch確認

ゲートウェイとファイル共有の作成時に、CloudWatch Logsやアラームの作成も行ったので、ここで確認しておきます。

ゲートウェイ用と、ファイル共有用のロググループが作成されています。

ゲートウェイ用のロググループです。
セットアップ時のログが記録されています。

ファイル共有用のロググループです。
先ほど、WindowsからS3にファイル共有されたことを示すログが記録されています。
S3からWindwosへのファイル共有に関するログは記録されていないようです。

こちらはCloudWatchアラームです。
ファイル共有のIOや共有失敗に関するアラームが作成されているので、必要に応じて通知を受け取れるようにするとよいでしょう。

SSH接続

Storage GatewayインスタンスへはSSH接続できます。
ただし、Storage Gateway用にカスタムされたものなので自由度は低そうですが、ここでネットワーク周りの設定や確認ができます。
ログインユーザは「admin」で、インスタンス作成時に作成したキーペアを使ってログインします。

まとめ

AWS Storage Gatewayを使用して、EC2に構築したWindowsに、他アカウントのS3バケットをドライブマウントすることができました。
作成するリソースが多く複雑なので、冒頭のような構成図を書き起こしてみることをお勧めします。
今回はAWS同士でしたが、オンプレミスや他ベンダーのクラウドサービスに立てたサーバから、S3をドライブマウントすることもできます。
ハイブリッドクラウド環境におけるデータ連携に非常に役立つ機能だと思います。

AWS CloudTrail LakeにAWS Configの情報を取り込めるようになりました

AWS CloudTrail LakeにAWS Configの情報を取り込めるようになったので、検証してみました。

aws.amazon.com

アップデート概要

AWS CloudTrail Lake は、CloudTrailログを取り込むことでSQLベースの分析を可能にします。
今回のアップデートで、Configの設定項目情報も取り込めるようになりました。
CloudTrailはユーザベースの調査を可能にする一方、Configはリソースベースの調査を可能にするため、これらを統合して分析することが可能です。

検証

イベントデータストアの作成

CloudTrail Lakeの画面から、「イベントストアの作成」を押下します。

イベントデータストアに適当な名前を付けます。

イベントタイプは「設定項目」を選択します。

内容を確認し作成します。

イベントデータストアが作成されました。

Config設定項目情報の検索

セキュリティグループ「test-sg」を作成します。

CloudTrail Lakeで以下のクエリを使って検索すると、作成したセキュリティグループに関する情報を得ることができました。

クエリ

SELECT
    eventTime, eventData.configuration, eventData.resourceId, eventData.resourceName, eventData.resourceType
FROM
    <config-event-data-store-id>
WHERE
    eventTime > '2022-12-02 16:00:00' AND eventTime < '2022-12-02 17:00:00' AND eventData.resourceName = 'test-sg'
ORDER
    BY eventTime DESC;

2つのイベントデータストアを統合して検索

事前にCloudTrail用のイベントデータストアを作成しておきます。

今度はセキュリティグループ「test2-sg」を作成します。
以下のクエリにより、CloudTrail用のイベントデータストアをとConfig設定項目情報用のイベントデータストアを統合して検索できます。
結果を見ると、CloudTrailとConfigの両方の情報が得られていることが分かります。

クエリ

SELECT
    config.eventTime, config.eventData.configuration, config.eventData.resourceId, config.eventData.resourceName, config.eventData.resourceType, userIdentity.username, trail.eventName, trail.eventSource
FROM
    <config-event-data-store-id> AS config JOIN <trail-event-data-store-id> AS trail ON config.eventData.resourceName = element_at(trail.requestParameters, 'groupName') 
WHERE
    config.eventTime > '2022-12-02 17:00:00' AND config.eventTime < '2022-12-02 18:00:00'
ORDER
    BY config.eventTime DESC;

まとめ

AWS CloudTrail LakeにAWS Configの設定項目情報を簡単に取り込み、検索することができました。
さらに、CloudTrailとConfigを統合して検索することができ、分析がしやすくなったのではないかと思います。

AWS Organizationsのポリシー管理を委任できるようになりました

AWS Organizationsのポリシー管理を委任できるようになったので、検証してみました。

aws.amazon.com

アップデート概要

これまで、AWS Organizationsのポリシー管理は組織の管理アカウントでしかできませんでした。
今回のアップデートで、ポリシー管理をメンバーアカウントに委任できるようになりました。

検証

Organizationsの「設定」→「委任」を押下します。

こちらのエディタで、誰に何を許可するかを定義できます。

例えば、メンバーアカウントでOrganizationsの画面を表示しようとすると、以下のよう表示できません。

そこで、先ほどのエディタで以下のように定義します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<accountID>:root"
            },
            "Action": [
                "organizations:List*"
            ],
            "Resource": "*"
        }
    ]
}

<accountID>は委任するメンバーアカウントで、今回は<accountID>に「organizations:List*」を許可しています。

再度、メンバーアカウントでOrganizationsの画面を表示しようとすると、今度は表示できました。

まとめ

アカウントが増えてくると管理を委任したいが、組織の管理アカウントに気軽にログインさせたくないケースが出てくると思います。
今回のアップデートで、マルチアカウントの運用の幅も広がるのではないかと思います。

Amazon InspectorがAWS Lambdaの脆弱性スキャンに対応しました

Amazon InspectorがAWS Lambdaの脆弱性スキャンに対応したようなので、検証してみました。

aws.amazon.com

アップデート概要

Amazon Inspectorは脆弱性を管理するためのサービスで、Amazon EC2Amazon ECRのコンテナイメージに、脆弱性が存在しないかを継続的にスキャンします。
今回新たに、AWS Lambda関数とAWS Lambda Layersの脆弱性スキャンに対応しました。
スキャン対象は、Java、NodeJS、および Pythonで記述された関数とレイヤーです。
スキャンタイミングは、Lambdaのデプロイ時、Lambdaの更新時、新しい脆弱性 ( CVE ) の公開時です。

検証

事前準備

Inspectorの画面です。
Lambdaの項目が増えています。

以前からInspectorを使用している場合は無効化になっているので、有効化する必要があります。

アカウント管理から、「有効化」→「Lambda標準スキャン」を押下します。

有効化されました。

Organizationを使っていれば、Inspector委任管理者アカウントから全アカウントまとめて有効化できます。
新しいメンバーアカウントを追加したときに、Lambdaスキャンが有効化になるように、「Lambda標準スキャン」にチェックを入れて保存しておきましょう。

検知させてみる

適当なLambda関数を作成します。

AWSから提供されている、「arn:aws:lambda:ap-northeast-1:249908578461:layer:AWSLambda-Python37-SciPy1x:118」レイヤーを追加してみました。

しばらくすると検知されました。

Lambda別画面で検出結果が見れます。

こちらは、全ての検出結果画面です。
脆弱性のタイトルから、検知の詳細を見ることができます。

まとめ

簡単にLambdaの脆弱性スキャンを行うことができました。
これまでambdaの脆弱性診断は、サードパーティ製品を使う必要がありましたが、ネイティブ機能で実施できる点はメリットだと思います。