問題文の日本語がムズすぎる

AWS SCS の対策をしているのだが、市販の対策問題集の日本語が酷い。

昔の本番試験も酷かったのでそのノリなんだろうが、今回は「それにしてもひどすぎる」と感じた。

この文章の意味を理解するのに20分は使ってしまった。

怒りに任せて筆を執ってるので後で冷静になったら消すかも。


極簡単なクロスアカウントKMSの問題。

答えは以下の操作を選ぶだけ。

  • アカウントAにおいてIAMロールを作成する
  • 上記IAMロールに対して、「アカウントBのKMSにアクセスできる」権限を持ったIAMポリシーを付与する

で、肝心のイケてない選択肢が以下。※解答は2

1)「アカウントAで、新しい Lambda 関数の IAM ロールを設定します。アカウントBで KMS キーへのアクセスを許可するキーポリシーをアタッチします。」

2)「アカウントAで、新しい Lambda 関数の IAM ロールを設定します。アカウント Bで KMS キーへのアクセスを許可する IAM ポリシーをアタッチします。」

私は1を選んで誤答だったのだが、以下のように文を読んだためだ。

1')「アカウントA内で、新しい Lambda 関数の IAM ロールを設定します。アカウントB内で KMS キーへのアクセスを許可するキーポリシーを(KMSキーに)アタッチします。」

2')「アカウントA内で、新しい Lambda 関数の IAM ロールを設定します。アカウント B内で KMS キーへのアクセスを許可する IAM ポリシーを(???に)アタッチします。」

2が正答ということは以下のように読み解くべきだったということだろう。

2'')「アカウントA内で、新しい Lambda 関数の IAM ロールを設定します。アカウント Bが保有する) KMS キーへのアクセスを許可する権限を持った) IAM ポリシーを(IAMロールに)アタッチします。」


上記文章の読みづらさは「で」の意味するものと、「何に対してアタッチするのか」の目的語が抜けていることに起因する。

特に「で」に関しては絶望的に読みにくい。

文2の前半では「アカウントA内で」というように 格助詞「で」の場所の用法 として使われている。しかし、後半の文の「で」は場所の用法として読むと私の誤答(2')のように読めてしまい誤答と判断してしまう。文2の「で」はどのように解釈したらいいのか今でもわからない。

SCS学習メモ

調べたことをつらつらと書いていきます。私自身の知識があやふやな部分のみまとめてるので網羅性はありません。

あくまで試験に合格することが目的なので深入りしていません。SCS の問題を解くのに必要と思われる範囲・深さの知識をまとめています。

個人の理解で書いてるのでたぶん結構厳密ではない書きぶりになります。間違ってる可能性もありますし、意図的に情報を端折ってる部分もあります。

受験日までこの記事を成長系ドキュメントとして更新していきます。

CloudTrail

保存期間

CloudTrail コンソールでは 90日間の履歴が見れる。

ログ出力のリードタイム

API イベント -> 15分以内 -> CloudTrail -> 5分間隔 -> S3

※リアルタイム監視には向いてない。必要に応じて、EventBridge / CloudWatch Events を利用すること。

ファイルの整合性の検証

ファイルの整合性の検証を有効にすると、ログのダイジェストファイルが作成され、S3に保存される。

CLIコマンドで検証を実行可能(裏で良しなにダイジェストファイルの比較をしてくれる)。

CloudTrail ログファイルの整合性の検証機能は有効化しておきましょう | DevelopersIO

オペレーションログ

DynamoDB のオペレーションログは CloudTrail で取れる。

AWS CloudTrail を使用して DynamoDB オペレーションをログに記録する - Amazon DynamoDB

証跡のクエリ

以下どっちかの方法。

  • CloudWatch Logs に送り、Insightsで見る。
  • S3 に送られた証跡を Athena でクエリ。

CloudWatch Logs Insights で監査ログの分析をしてみる #reinvent | DevelopersIO

[AWS ]CloudTrailの証跡ログをAthenaを使ってサクッと解析する[このリソース誰が作ったの?] | DevelopersIO

また、別アカウントのS3バケットに直で流し込むことができる。

読み取り専用・書き込み専用イベント

  • 読み取り専用イベント:List とか Describe といった R 的なイベント
  • 書き込み専用イベント:Create とか Delete といった C, U, D 的なイベント

CloudTrail コンソールでは「読み取り専用」を true / false 切り替えでフィルタリング可能。

[新機能]AWS CloudTrailのイベント履歴のフィルターに読み取り専用とAWS アクセスキーが追加されました | DevelopersIO

Trusted Advisor

他サービス連携

EventBridge のイベントソースとして Trusted Advisor を利用できる。

使用例

  • Trusted Advisor -> EventBridge -> SNS (管理者通知)
  • Trusted Advisor -> EventBridge -> Lambda (是正措置:公開されたアクセスキーを検知し、そのアクセスキーを無効化するなど)

Config

CloudTrail との使い分け

CloudTrail でいいじゃんと思っていたのであんまり使ったことなかった。

※ CloudTrailでも出来るじゃんと思われるかと思いますが、あちらは呼び出されたAPIを全て記録していますので、量がハンパないです。

AWS Configでひとまず確認し、詳細はCloudTrailという併用がベストかと思います。

CloudTrailとConfigはどちらか、ではなくどちらもなのです。

AWS再入門 AWS Config編 | DevelopersIO

また、CloudTrail しか使っていなかった場合、「CloudTrail が無効化された」時に為す術がなくなる。

Config で CloudTrail が無効になったことを検知するルールを設定し、検知後に EventBridge を介して CloudTrail を再有効化する Lambda を実行すれば自動で復旧できる。

Config について

Config では大体の主要なサービスはサポートされてる。

構成管理といったネーミングから VPC や EC2 といったイメージが先行するが、S3 の変更検知や IAM の変更検知などなどなんでもできそう。

「変更"検知"」と聞かれた場合は CloudTrail というよりは Config と回答した方がよい気がする。

サポートされているリソースタイプ - AWS Config

Config からの自動復旧・通知パターン

  • Config -> EventBridge -> Lambda
  • Config -> EventBridge -> SNS
  • Config -> SSM Automation(Run Book)

GuardDuty

脅威 "検知" サービス。有効化するだけでOK。

CloudTrail、 DNSログ、 VPCフローログ、 S3 イベントログ、 EKS 監査ログ 等のログを収集して「悪意のあるアクティビティ」を検出。

例えばマイニングに利用されてるとか。

信頼されたIPをホワイトリスト形式で登録することで抑制が可能。

あくまで「検知」サービスのため、通知するには EventBridge -> SNS などの通知サービスとの連携が必要になる。

特に設定しなくても Security Hub 側でも管理が可能。

AWS再入門ブログリレー2022 Amazon GuardDuty 編 | DevelopersIO

Organizations で管理アカウントに流すことも可能。全てのアカウントで GuardDuty を有効化し、アカウントの招待・受け入れを行えばよい。

外部IDでのアクセスパターン

TODO:いろいろパターンがあるのでまとめたい or わかりやすくまとめてるサイト探す

AD Connector

AD のユーザーとグループを IAM ロールに紐づける。

  1. ログイン後の権限を付与したIAMロールを作成
  2. AD の IdP との信頼関係をロールに設定(証明書利用者の信頼)
  3. ユーザはADでの認証後、ロールを引き受けてコンソールログイン

Active Directoryを活用したAWS Management ConsoleへのSSO(AD Connector編) | DevelopersIO

AWS Managed Microsoft ADの認証情報を使ってAWSマネジメントコンソールにログインしてみた | DevelopersIO

証明書利用者の信頼およびクレームの追加によって SAML 2.0 IdP を設定する - AWS Identity and Access Management

ADFSを利用したログインは未調査(Active Directory資産を活用したAWS Management ConsoleへのSSO | DevelopersIO

SAML によるコンソールアクセス

  1. IdP で認証 -> IdP から SAML アサーションを受け取る
  2. AWSサインインエンドポイントへリダイレクトされる
  3. AWS エンドポイントは STS から一時認証情報を受け取り、サインインURLを作成
  4. サインインURLにリダイレクトされる

SAML 2.0 ベースのフェデレーションについて - AWS Identity and Access Management

SAML による API アクセス

  1. IdP で認証 -> IdP から SAML アサーションを受け取る
  2. STS へ AssumeRoleWithSAML を呼び出す -> 一時認証情報を受け取る
  3. 一時認証情報を使い API アクセス

SAML 2.0 ベースのフェデレーションについて - AWS Identity and Access Management

ウェブIDフェデレーション

外部IdPで認証し、その結果をもとに一時認証情報を利用してデータアクセスする。

単純なケースでは Cognito は必要ない。※ただし AWS 的には Cognito 推奨

STS を利用したケース:Cognito不要)

  1. 外部 IdP へログイン -> トークンを取得
  2. STS へトークンを渡す -> 期限付きの認証情報を取得
  3. 期限付きの認証情報を使いデータアクセス

IDプール を利用したケース)

  1. 外部 IdP or Cognito ユーザプールへログイン -> トークンを取得
  2. トークンを Cognito ID プールへ渡す -> 一時クレデンシャルを取得
  3. 一時クレデンシャルを利用しデータアクセス

WebIdentityFederationとCognito - Qiita

AWS再入門ブログリレー Amazon Cognito編 | DevelopersIO

API Gateway で認証済みユーザのみにアクセスを制限する場合はオーソライザーを使用する。

処理の流れ)

  1. Cognito ユーザプールにログイン -> ユーザプールトークン・IDトークンを取得
  2. API Gateway に IDトークンを持ってリクエスト
  3. API Gateway 側で Cognito に検証リクエストを送る

Cognito ユーザプールに外部IdPを設定すれば、外部IdPで認証済みのユーザに対して上記の処理が実装できる。

現在は JWT オーソライザーを利用して Cognito 不要で外部IdP認証からの API リクエストが可能になった(もちろん Cognito でもできる)。

Amazon API Gateway Cognito オーソライザーに送信する ID トークンのフォーマットに注意 – TechHarmony

HTTP APIのJWTオーソライザーを使ってCognitoユーザープールと連携してみる | DevelopersIO

DynamoDB のユーザ自身のレコードにしかアクセスさせたくない場合は以下のようにポリシーに設定することで、IDとパーティションキーのマッピングができる(IDとパーティションキーが一致するアイテムのみにアクセス可能)。

"dynamodb:LeadingKeys": [
    "${www.amazon.com:user_id}"
],

ウェブ ID フェデレーションの使用 - Amazon DynamoDB

IAM Identity Center を利用した SSO 構築

IAM Identity Center = 旧 AWS SSO

超ざっくり構築手順

  1. 外部 IdP を準備
  2. アイデンティティセンターの ID ソースとして外部 IdP を指定。
  3. アイデンティティセンターで IAM ユーザを作成。
  4. アイデンティティセンターのコンソールでユーザをアカウントに割り当てる。

【AWS IAM Identity Center】Google Workspaceの代わりにCloud Identityを使ってGoogleアカウントからのシングルサインオン環境を作る - サーバーワークスエンジニアブログ

Organizations

Organizations の機能セット

  • 一括請求(コンソリデーティッドビリング)のみ -> SCP利用不可
  • すべての機能(All Feature)

OU(Organization Unit)を利用し、複数のアカウントをグルーピングすることができる。

Root の下に OU のネスト構造(木構造)が広がってるイメージ。

SCP は ルート -> OU -> 特定のアカウント で継承される。ベストプラクティス的には「OU に対して SCP を適用し、アカウントへは FullAWSAccess を付与する(OU で SCP を管理し、アカウントには継承させる)」。

デフォルトで「すべてのルート」「OU」「アカウント」に FullAWSAccess ポリシーがアタッチされているので、必要に応じて削除し適切な SCP を設定する必要がある。

ポリシーの強さは 「暗黙の Deny < 明示的な Allow < 明示的な Deny」。

例)

  • OU側SCP:EC2許可 / Lambda拒否
  • アカウント側SCP:S3許可 / Lambda許可

結果:S3拒否(OU側SCPの暗黙的Deny)、Lambda拒否(OU側SCPの明示的Deny)

[AWS Organizations] SCP(サービスコントロールポリシー)の継承の仕組みを学ぼう | DevelopersIO

IAM

Principal の root

"Principal": { "AWS": "arn:aws:iam::123456789012:root" } はアカウント全体を指す(rootユーザという意味ではない)

AWS JSON ポリシーの要素: Principal - AWS Identity and Access Management

ABAC

通常の RBAC とは異なる概念で ABAC(Attribute Based)がある。

これは以下のように aws:ResourceTagaws:PrincipalTag の組み合わせでタグベースでの認可を行うもの。

RBAC とは異なり、IAM ポリシーは一つのみで、あとはタグの付け替えで制御する考え方。

プリンシパルが頻繁に変更されるケースだと使えるかもしれない。(が、意図したとおりに動くかとか、管理するためのコンソールがないのでムズそうだなといった印象)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "AWSサービス:アクション名",
            "Resource": "arn:aws:AWSサービス::AWSアカウント番号:リソース種別/*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/タグキー": "${aws:PrincipalTag/タグキー}"
                }
            }
        }
    ]
}

※参照元からコピペさせてもらいました。

このアクション、ABAC ないし RBAC に対応してる?難解な IAM リファレンスに立ち向かうための地図を描いてみた | DevelopersIO

MFA

IAM コンソールで MFA デバイスの割り当てを開始したにも関わらずプロセスをキャンセルした場合に、MFA デバイスを削除できなくなることがある(iam:DeleteVirtualMFADevice 権限がない)。

CLI や API を利用して削除可能。

一般的な IAM の問題のトラブルシューティング - AWS Identity and Access Management

CloudWatch

エージェント

CloudWatch エージェント(現)= CloudWatch エージェント(旧)+ CloudWatch Logs エージェント(旧)

CloudWatch Logs のフィルターは「メトリクスフィルター」。「ログフィルター」なんて名称はない。

CloudWatch Logsエージェント環境にCloudWatch統合エージェントへウィザードを使って設定を引き継いだ場合の挙動を確認する | DevelopersIO

ログファイル

通常ログファイルはローテーションされるのでローテーション方式によって、file_path を適切に設定する。

OS側でファイルへの権限を当てる必要がある。

CloudWatch Agentでワイルドカードを使用して可変名称のログをCloudWatch Logsへ転送してみた | DevelopersIO

Lambda実行ロール

Lambda から CloudWatch Logs にログを流すためには以下の3つが必要(これはちゃんと暗記する)。

  • logs:CreateLogGroup
  • logs:CreateLogStream
  • logs:PutLogEvents
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:*:*:*"
            ]
        }
    ]
}

おそらく既存のロググループを利用する場合は CreateLogGroup は必要なく、Resource としてLogGroup名まで書けばよい。

CloudWatch Events

現在新しく作成する場合には EventBridge を利用することが多いが、試験問題としては Events も出題される可能性がある。

VPC

DNS設定

  • enableDnsHostnames: VPC がパブリックIPアドレスを持つインスタンスへのパブリックDNSホスト名の割り当てをサポートするかどうか。デフォルト false。
  • enableDnsSupport: VPC が Amazon 提供の DNS サーバを介した DNS 解決策をサポートするかどうか。デフォルト true。

VPC の DNS 属性 - Amazon Virtual Private Cloud

パケットキャプチャ

VPC内のパケットキャプチャ方法の例。

  • プロキシ/リバプロを構築
  • EC2にサードパーティソフトをインストール
  • VPC Traffic Mirroring を利用

※CloudWatch エージェントや Inspector ではパケットキャプチャできない。

※VPC フローログではパケットはキャプチャされているが、その情報をサマったものが出力されるためパケット検査には利用することができない。

VPCフローログにすべてのトラフィックが記録されないのはなぜですか - Serverworks

【ハンズオン】VPCトラフィクミラーリングを使ってEC2にログインせずにパケットキャプチャする方法を学ぼう#AWSSummit | DevelopersIO

トラフィックの監視

NACLやセキュリティグループの設定が機能しているかどうかは以下で確認可能。

  • VPCフローログ -> S3 -> Athena で分析
  • VPC Reachability Analyzer を利用 ※ Inspector の Network Reachability とは別モノなので注意

Config ルールでの検出は設定が "機能しているか" に主眼を置いていないのでダメ。

EC2

キーペア変更方法

パブリックキーの場所は ~/.ssh/authorized_keys

変更方法は以下のいずれか。

  • AMIを作成。AMIからインスタンスを起動するときに別のキーペアを指定。
  • 上記の公開鍵を直接置き換える。

ただし、AMIを利用したキー変更の場合、古いキー情報も残ったままになるので手動で削除が必要。結局公開鍵を直接置き換えるのと労力変わらない気がする。

インスタンスでパブリックキーを追加または削除する - Amazon Elastic Compute Cloud

Run Command(実行コマンド)

外からコマンドが叩ける。「実行コマンド」と訳される場合があるので注意。

Windows でも Linux でも可。Linux の場合、SSMエージェントが必要。※Run Command は Systems Manager の一部の機能

セキュリティインシデント発生時の対応

セキュリティインシデント時のデータを失わないために以下を実施する。

  • インスタンスの保護とタグ付け
    • 終了保護ON
    • EBS終了時の削除OFF
    • 検疫中タグ
  • インスタンスデータ取得
    • EC2メタデータ取得
    • EBSスナップショット取得
    • メモリダンプ取得
  • インスタンスをシステムから切り離す
    • AutoScalingグループから切り離す
    • ELBから切り離す
    • セキュリティグループの許可を削除(フォレンジック・テレメトリデータ用の通信は残す)

AWS セキュリティインシデント対応ガイドを要約してみた。これを読んでインシデントに備えよう | DevelopersIO

IDS/IPS

当たり前の話ではあるが、EC2内のセキュリティはユーザ側で担保する必要がある。

EC2はプロミスキャスモードが禁止されているので自前で導入はムズい。ホスト型 IDS の導入は MarketPlace で AMI を探せば OK。

Amazon EC2でIDS(侵入検知システム)を導入する – AIDE – | DevelopersIO

メタデータ取得先

http://169.254.169.254/latest/meta-data

https(443)は不可。http(80)のみ。

また、メタデータオプションでメタデータへのアクセスを無効にすることもできる。

NAT インスタンスとしての利用

送信元/送信先チェックを無効にする。

デフォルトは有効。NAT インスタンスはトラフィックの送信元でも送信先でもなくただの中継地点のためチェックを無効にする必要がある。

EC2 Image Builder

そもそも何者かよくわかってない。※もちろん用途はわかるけども

調べた限り、ビルドを実行するインスタンスとして EC2 をどっかの VPC に置く必要があって、AWS が裏で(見えないところで)よしなに全部やってくれるわけではなさそう。何も考えずに使う分にはデフォルト VPC を使うみたいなので「AWS が裏でよしなにやってくれる」ように見えてるだけっぽい??

プライベートサブネットで利用するためには、VPC エンドポイントとして Image Builder、SSM のエンドポイントを作成する。必要に応じてインストールパッケージの置かれた S3 エンドポイントも。

[アップデート] EC2 Image Builder が PrivateLink に対応しました | DevelopersIO

Inspector

検索タイプ

  • パッケージの脆弱性(CVEにあるソフトウェアパッケージ)
  • Network Reachability

Network Reachability ではポートスキャンの "ような" ことができる。

実際は VPC、サブネット、ACL、セキュリティグループ、IGW、VGW、Direct Connect、ELB などの設定を分析している。

Inspector エージェントをインストールすれば、インスタンスで動作しているプロセス情報(ポートリッスン)を評価できる。

Amazon Inspector でのタイプの検索 - Amazon Inspector

Amazon Inspectorに新しいルールパッケージが追加されてEC2インスタンスに対するネットワークアクセス制御を評価できるようになりました。 | DevelopersIO

Amazon Inspectorでネットワークアセスメント(Network Reachability)をやってみた | DevelopersIO

ELB

ELB - EC2 間の通信

ELBとEC2間の通信については以下いずれのパターンも可。

  • ELB /w 証明書 ->(HTTP)-> EC2
  • ELB /w 証明書 -> (HTTPS) -> EC2 /w 証明書 ※1
  • ELB -> TCPスルー -> EC2 /w 証明書 ※2

※1:ELBでクライアントとのSSL終端、再暗号化しEC2へ流す(SSLリスナーを設定)

※2:EC2 で SSL 終端させたい場合は EC2 に TCP のままスルーできる

AWSでWebサイトをHTTPS化 全パターンを整理してみました – ナレコムAWSレシピ | AIに強い情報サイト

セキュリティポリシー

  • プロトコル(TLSバージョン):ELBSecurityPolicy-TLS-XXX など
  • 暗号スイート(アルゴリズム):ECDHE-ECDSA-AES128-GCM-SHA256 など
  • サーバの優先順位 ← よくわからん

ELB のセキュリティポリシー変更はブラウザの対応プロトコルを考慮して慎重に | DevelopersIO

NACL・セキュリティグループ

FQDNサポート

NACL・セキュリティグループともに FQDN を指定することはできない。

ドメインで制御したいなら、

  • AWS Network Firewall を利用する
  • EC2 上に自前でプロキシを構築する(アウトバウンド制御の場合)

セキュリティグループのインバウンドルールで、ソースを IP アドレスではなく FQDN で指定できますか? - サーバーワークスエンジニアブログ

NACL

ステートレスなのでクライアント側のポートが絞れない場合はエフェメラルポート(一時ポート)を幅で設定する必要がある。

[小ネタ]NACLでHTTP通信を制限する際の注意点 | DevelopersIO

セキュリティグループ

同じセキュリティグループがアタッチされた EC2 同士はプライベートで通信するので、パブリックで通信させたければ別セキュリティグループにしてパブリックの送信/受信を許可する。

実際にはパブリックIPでの通信の場合も AWS ネットワーク内で完結するみたい。「≠ プライベート」なので勘違いしないように。

インスタンス間のパブリックIPでの通信は本当に外部に出ないのか試してみた | DevelopersIO

ECS

ネットワークモード

ECS on EC2 の場合のネットワークモード

  • ブリッジ:EC2のポートとコンテナのポートをマッピング(ポートが違ってOK)。ENIはタスク間で共有。
  • ホスト:コンテナで expose されたポートをホストでも利用する。ENIはタスク間で共有。
  • awsvpc:ENIがタスク毎にアタッチされる。タスク毎に管理できるのでこれがベストプラクティスっぽい。
  • なし:ポートマッピングなし(外部接続できない)。

ECSでEC2インスタンスを利用する際のネットワークモードについて調べてみた | DevelopersIO

DDoS 対策

  • AWS WAF(レイヤー7)
  • AWS Shield Standard(レイヤー3, 4)/Advanced(レイヤー7)

AWS Shield が統合されるサービス

  • CloudFront
  • ELB(ALB, CLB)
  • Route53

AWS Shield Advancedを試してみた | DevelopersIO

AWS WAF vs AWS Shield - 協栄情報ブログ

また、DDoS シミュレーションテストは基本的には NG で、APN パートナー(DDoS テストパートナー)によって実施される必要がある。

パブリック DDoS テストポリシー – アマゾン ウェブ サービス (AWS)

WAF

レートベースのルール

レートベースルールを利用し、アクセス数が一定回数を超えた IP アドレスを自動的にブラックリストに追加できる。

レートベースルールは、発信元 IP のリクエスト数のカウント値が閾値を越えた場合に自動でブロックするルール。

閾値を超えてから1~2分程度でブロックされ、そこから5分間はブロックされる。5分後に閾値を下回っていれば1~2分でブロックが解除される。

AWS WAF でアクセス数が一定回数を超えた IP アドレスを自動的にブラックリストに追加させる方法 | DevelopersIO

AWS WAF のレートベースのルールステートメントのブロックが開始されるタイミングと評価期間を教えてください | DevelopersIO

Route53

DNSSEC 署名の有効化

そもそも DNSSEC とは、DNS レコードに追加される暗号化署名。キャッシュポイズニングを防止できる。

有効化手順

  1. KSK(Key Signing Key)を作成し、DNSSEC 署名を有効化する。
  2. DS レコードを作成する。※

※DSレコードは親ゾーンの管理者に送る公開鍵のハッシュ値。親ゾーンの管理者は秘密鍵で署名し公開。このチェーンを「信頼の連鎖」と呼ぶ。

インターネット10分講座:DNSSEC - JPNIC

KMS

平文のデータキーは使ったらすぐ捨てる。暗号化されたデータキーを無くすと復号できなくなるので注意。

暗号化処理の流れ

  • マスターキーはAWSが保管
  • マスターキーIDを指定してデータキー作成をリクエストすると、平文データキーと暗号化されたデータキーが返却される
  • 平文のデータキーを使って暗号化。
  • 暗号化データと暗号化されたデータキーを一緒にどっかに格納
  • 平文のデータキーを捨てる

復号処理の流れ

  • マスターキーIDと暗号化されたデータキーをKMSに渡すと、平文のデータキーと暗号化されたデータキーが返却される。
  • 平文のデータキーを使用してデータを復号する。
  • 平文のデータキーを捨てる。

10分でわかる!Key Management Serviceの仕組み #cmdevio | DevelopersIO

キーローテーション

自動/手動のいずれにしてもアプリケーションの改修やデータの再暗号化は必要ない。

ローテーションしたマスターキーはキーマテリアルが異なる。

キーマテリアルを自分で持ち込んだ(インポートした)場合、自動キーローテーションは利用できない。手動キーローテーションはできる。

※キーマテリアルをインポートすると、有効期限・自動削除が設定できる。マネージドキーではできない。

自動キーローテーション

365日間隔でマスターキーを自動ローテーションする。それより短い期間でやりたいなら手動。

ローテーションすると、エイリアス、キーIDはそのままでキーマテリアルが更新される。

すでに暗号化済みのデータキーに対するマスターキー(キーマテリアル)は復号化のために残る(削除されない)。

手動キーローテーション

新しいキーIDが作成される(新しいマスターキーを作るにほぼ等しい)。

エイリアスを新しいマスターキーに紐づけ直すことができる。そのためアプリケーションの改修は必要ない。

【AWS Tips】SSE-KMSとキーローテーションの目的・仕組み - 顧客フロントSEのIT勉強ブログ

【新機能】AWS Key Management Serviceの新API「UpdateAlias API」でキーローテーションが簡単確実に! | DevelopersIO

クロスリージョン・クロスアカウント

リージョン間でKMSを共有する必要がある場合はKMSキーがあるリージョンへリクエストする必要がある。

基本的にKMSキーはリージョンをまたいで複製することはできない。

現在では「マルチリージョンキー」がサポートされており、リージョン毎にレプリカキーを作成して利用することができる。

マルチリージョンキーをサポートしたKMSを試してみた | DevelopersIO

クロスアカウントで利用したい場合はキーポリシーに別アカウントの設定を記述する。

他のアカウントのユーザーに KMS キーの使用を許可する - AWS Key Management Service

キーポリシー

キーポリシー概要

リソース -> IAMロール -> IAM ポリシー -> キーポリシー -> KMS

AWS KMS CMK(Customer Master Key)のキーポリシーとIAMポリシーの組み合わせのアクセス制御と、キーポリシーのみのアクセス制御を試して設定の違いをみてみた | DevelopersIO

キーポリシーにMFA強制を Condition で持たせることもできる。

Amazon Web Services (AWS) Key Management Service (KMS) Encryption Plugin Advanced Usage - MariaDB Knowledge Base

Auto Scaling Group で暗号化 EBS を利用する場合

EBS 自体にKMSキーを利用する許可を与えたい。通常であれば、EBSにIAMロールを定義し、キーポリシー側でEBSのIAMロールからの利用を許可する流れとなる。しかし、EBS にはロールをアタッチすることができない。

そのため、キーポリシーに、Auto Scaling Group の IAMロールに対して EBS(AWSサービス) への鍵の利用を許可する設定(kms:CreateGrant)を行う。

{
  "Sid": "Allow attachment of persistent resources",
  "Effect": "Allow",
  "Principal": {
    "AWS": [
      "arn:aws:iam::111122223333:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling_CMK"
    ]
  },
  "Action": [
    "kms:CreateGrant"
  ],
  "Resource": "*",
  "Condition": {
    "Bool": {
      "kms:GrantIsForAWSResource": true
    }
  }
}

Service-Linked RoleによるAuto Scaling Groupsで暗号化されたEBSボリュームを使用する | DevelopersIO

AWS KMS のキーポリシー - AWS Key Management Service

特定の AWS サービスにのみ許可

kms:ViaService を指定する。

"Condition": {
  "StringEquals": {
    "kms:ViaService": "ec2.us-west-2.amazonaws.com"
  }
}

AWS KMS 条件キー - AWS Key Management Service

その他

面白そうなので試験受かったらちゃんと読む(フラグ)。

暗号化されたEBSボリュームを作成できずハマった話 | DevelopersIO

CloudHSM

ユースケース

そもそもHSMって何?ってレベルから。。。

HSM=ハードウェアセキュリティモジュール

VPC内にマネージドなクラスターとしてFIPS検証済の専用ハードウェアをデプロイする。

ハードウェアは専有なのでKMSより高い。

ユースケース例)

  • ウェブサーバのSSL/TLS処理のオフロード
  • 発行元の認証機関(CA)の秘密鍵
  • Oracle DB の透過的なデータ暗号化(TDE)を有効化

いずれにしても、ELB + Certificate Manager でいいのでは? KMS でいいのでは? RDS でサポートされる TDE でいいのでは? みたいな疑問はあるが、「FIPS対応」が必要な場合には CloudHSM じゃないと対応できないケースはあるだろうと思う。

HSMとは・ハードウェアセキュリティモジュールとは

【AWS】CloudHSMの使い方について – Amazon Web Service(AWS)導入開発支援

AWS CloudHSM ユースケース - AWS CloudHSM

コマンドラインツール

HSMユーザの管理:cloudhsm_mgmt_util キーの管理:key_mgmt_util

Systems Manager

SSM Automation

AWS リソースのメンテナンスを自動化するための機能。事前定義 or カスタムで利用可能。

Config で非準拠とされたリソースに対しての修復といった使い方ができる。

AWS Systems Managerオートメーションランブックを利用して非準拠ステータスのAWS Configルールを修復する | Amazon Web Services ブログ

運用の効率化を支える AWS Systems Manager Automation の紹介 | sreake.com | 株式会社スリーシェイク

SSMオートメーションを試しました | DevelopersIO

AWS Config ルールによる非準拠リソースの修復 - AWS Config

SSM Patch Manager

EC2 のパッチ管理に利用する。

前提条件

  • SSM エージェントが導入されている
  • SSM エンドポイント・パッチリポジトリと通信できる ※
  • IAM ロールが適切に設定されている

※必要に応じて NAT GW とかが必要になる。

【AWS Systems Manager】パッチマネージャー実行時の関連リソースを、絵で見て(完全に)理解する。 | DevelopersIO

【AWS Systems Manager】パッチマネージャーの パッチベースライン と パッチグループ の概念を勉強する | DevelopersIO

【脆弱性対応】AWS Systems Manager Patch Manager を使ったパッチ戦略の例 | DevelopersIO

SSM Parameter Store

Systems Manager パラメータストアでは KMS による暗号化がサポートされている。

アプリで直接見る必要のないライセンスキーやパスワードに関しては SecureString パラメータを使用する。

以下の権限をIAMユーザ/ロールに設定する。

  • SSM の参照権限
  • CMK の利用権限(CMK のキーユーザ or IAM)

パラメータストアでの KMS のトラブルは主に以下の3つ

  • 権限問題(上記)
  • KMS キーが見つからない(設定したID・エイリアスが間違っている)
  • KMS キーが有効になっていない

AWS KMS で EC2 Systems Managerパラメータストアを暗号化 | DevelopersIO

AWS Systems Manager Parameter Store が AWS KMS を使用する方法 - AWS Key Management Service

Sectets Manager

SSM Parameter Store との使い分け

パスワードのローテーションするならこっち。Parameter Store では自動ローテーションはサポートされていない。

また、KMSキーの管理もこっち。Parameter Store は「シークレット情報」の管理であり、「キー」の管理ではないことに注意。

ローテーションを有効にした場合は、シークレットを保存するとすぐにシークレットが一度ローテーションされる。

ローテーションには Lambda が利用される。RDS のパスワードを更新するには Lambda が RDS に接続できる必要があるため注意(VPC Lambda を利用)。

S3

HTTPS 強制

HTTPSを強制するにはバケットポリシーで aws: SecureTransport 条件を利用する。

バケットポリシー

Principal に IAM グループを指定することができないので注意。

バッチオペレーション

バケットに保存されているオブジェクトに対して一括で API を実行できる機能。

非暗号化オブジェクトを一括で暗号化するために使える。

複数のS3のオブジェクトをまとめて一括処理!Amazon S3 Batch Operationsを試してみた | DevelopersIO

オブジェクト所有権のバケット所有者の強制

バケット所有者強制設定(ACL 無効オプション)を適用すれば、他アカウントがアップロードしたオブジェクトも自アカウントで所有できる。

オブジェクト所有権は ACL を利用して設定するもので、バケットポリシーで設定するものではないので注意。

別のアカウントが所有する Amazon S3 オブジェクトの所有権を変更する | AWS re:Post

例 3: バケット所有者が自分の所有していないオブジェクトに対するアクセス許可を付与する - Amazon Simple Storage Service

Glacier

ボールトロック

  1. ボールトロックIDを取得:InitiateVaultLock 呼び出し
  2. 24時間ロック状態になる:InProgress ステータス
  3. 24時間の間にセキュリティ観点でのテストをする
  4. テストOKならロックIDを指定してロック確定:CompleteVaultLock 呼び出し、Locked ステータス

S3 Glacierのボールトロック - あのときの、ほら!あれ、あれ!

Macie

SSE-S3、SSE-KMS の場合はデータの中身まで見てくれる。SSE-C の場合は無理(メタデータのみ検査)。

Amazon Macie を用いた暗号化された S3 オブジェクトの分析 - Amazon Macie

Athena

Athena へのアクセスを行うリソースに付与するロールには Athena が利用する S3 バケットへのアクセス権限も付与しないと Athena クエリが失敗する。

Redshift

保存時の暗号化はクラスタ起動時に設定する。

クラスタ起動後も KMS を利用して暗号化を有効にできる(その場合暗号化が有効になった新たなクラスタにデータが移行される)。

暗号化を有効化すればスナップショットも暗号化される。

CloudFront

CloudFront + S3

セキュリティ的には以下が重要ポイント。

  • S3 へのアクセスを CloudFront に制限する
    • OAI (Origin Access Identity)または OAC(Origin Access Control)を利用する。※
    • S3側のバケットポリシーで OAI からのアクセスのみに絞る
  • HTTPS 強制
    • CloudFront 側で HTTP アクセスを HTTPS にリダイレクトさせる
    • バケットポリシーで aws: SecureTransport 条件を利用する。

※OAC は OAI の高機能版で、SSE-KMS に対応している。

注意事項

  • CloudFront とオリジン間の HTTPS 通信に自己署名証明書は利用できない。
  • CloudFront で ACM(AWS Certificate Manager)証明書を利用するにはバージニア北部リージョンにインポートする必要がある。※確かにグローバルサービスだもんね。
  • セキュリティヘッダを付与する場合には Lambda@Edge を利用する。

Amazon CloudFront でオリジンを Amazon S3 にするときのパラメータに注意 – TechHarmony

Amazon CloudFrontの従来のOAIから新しくなったOACに移行してみた | DevelopersIO

CloudFront+S3環境でLambda@Edgeを用いてHTTPセキュリティヘッダーを付与する方法 - サーバーワークスエンジニアブログ

CloudFront とカスタムオリジン間の通信で HTTPS を必須にする - Amazon CloudFront

署名付きURL

CloudFront の署名付き URL / 署名付き Cookie を作成するためには「信頼された署名者」が必要となる。

以下のどっちかを指定。

  • CloudFront で作成した「信頼されたキーグループ」※推奨
  • CloudFront のキーペアを含む 「AWSアカウント」

署名付き URL と署名付き Cookie を作成できる署名者の指定 - Amazon CloudFront

CloudFront + WAF + Lambda@Edge

  1. CloudFront ログを Lambda@Edge で読む
  2. 不正なリクエストをフィルターし、不正元にダミーレスポンスを返す
  3. WAF に不正元をブロックする設定を追加する

[レポート] Amazon CloudFront、AWS WAF、およびLambda@Edgeを使ってスパマーを排除する #CMY303 #reinvent | DevelopersIO

【AWS re:Invent2019】CMY303 – Using Amazon CloudFront, AWS WAF, and Lambda@Edge to keep spammers outを受講しました | クラウド・AWSのIT技術者向けブログ SKYARCH BROADCASTING

DynamoDB

保存時の暗号化はテーブル作成時のみ可能。既存の非暗号化テーブルに対して暗号化を有効にすることはできない。

Kinesis

暗号化

Kinesis Data Stream のサーバ側暗号化ではKMSキーで Kinesis ストリームのストレージに書き込まれる前に暗号化される。

Kinesis Data Firehose のサーバ側暗号化はよくわからん。S3 に保存する際の暗号化は指定できるようだが、配信ストリーム内の暗号化はなさそう???少なくとも、配信元が Data Stream の場合は復号されたデータが飛んできて、そのままメモリにバッファして保存することなく S3 に配信されるよう。そもそも保存してないんだから暗号化する必要はないかもしれないが、Data Stream とFirehose の間はどうなってるのかよくわからない。

Amazon Kinesis Data Firehose のデータ保護 - Amazon Kinesis Data Firehose

「データフロー全体において配信中・保存中の暗号化」が要件にある場合は Data Stream を解答するのが安全か。

EFS

転送中・保管時の暗号化

  • 保管時:EFS作成時に有効化。
  • 転送中:EFSファイルシステムをマウントするときにTLSを有効化。

SNS

SMS送信数には使用制限がある。Emailにはなさそう。

IoT Core

IoT Core Policy で複数の「モノ」をセキュアに管理するために以下のポリシー変数が利用できる。

  • iot:Connection.Thing.IsAttached:証明書や Cognito ID が IoT のモノにアタッチされている場合 true を返す
  • iot:Connection.Thing.ThingName:クライアント ID から IoT のモノの名前を返す。※1
  • iot:ClientId:セキュリティリスクがあるため ThingName を利用すること。※2

※1:モノの名前=クライアントIDである必要がある

※2:上2つはいずれもデバイス証明書を使用して接続時に値を取得するようで、第三者がクライアントIDを偽って接続することを防ぐ効果があるよう。

[AWS IoT] ポリシー変数で複数のモノをセキュアに管理してみた | DevelopersIO

DynamoDB 属性レベル制御とちょっとだけ項目レベル制御

具体的によく知らなかったので調べた。

最近のデバイスはハイスぺなんで、一部の項目だけに絞ってサイズを小さくするってこともあんまりないし、特定アイテム(レコード)内でのデータの可視範囲を制御したいならそのデータはDynamoDBの外部に置いておく方が安全だし、あんまり使いどころがわからん。

あーでも実際にはアプリからのリクエスト時には(普通なら) API Gateway とか AppSync 経由でするように設計するんで API 開発はしやすいかもしれない。あとたぶんデータ転送量も抑えられるのでめちゃでかいシステムなら恩恵あるかも???

というのは個人的な貧相な経験からの感想だが、よくよく考えてみると、「DynamoDBのテーブル数は少ない方がよい。優れた設計はテーブル1つだ!」といった思想があった気がする。テーブル一つなら属性レベル制御絶対に必要だよね。

とりま試験のための勉強なんで概要だけをさらっと。

項目レベル制御と属性レベル制御

docs.aws.amazon.com

項目レベル制御: 項目レベルでアクセス可能・不可を制御。

属性レベル制御:属性レベルでアクセス可能・不可(可視・不可視)を制御。

利用イメージ(属性レベル制御)

docs.aws.amazon.com

docs.aws.amazon.com

GetItem, Query, Scan オペレーション実行時にプロジェクション式(projection expression)を指定することで特定の属性のみに絞ることができる。

例えば、以下の項目があったとする。★の部分のみが欲しい。

{
    "Id": 123,
    "Title": "Bicycle 123",
    "Description": "123 description",・・・★
    "BicycleType": "Hybrid",
    "Brand": "Brand-Company C",
    "Price": 500,
    "Color": ["Red", "Black"],
    "ProductCategory": "Bicycle",
    "InStock": true,
    "QuantityOnHand": null,
    "RelatedItems": [
        341,・・・★
        472,
        649
    ],
    "Pictures": {
        "FrontView": "http://example.com/products/123_front.jpg",
        "RearView": "http://example.com/products/123_rear.jpg",
        "SideView": "http://example.com/products/123_left_side.jpg"
    },
    "ProductReviews": {
        "FiveStar": [・・・★
                "Excellent! Can't recommend it highly enough! Buy it!",
                "Do yourself a favor and buy this."
        ],
        "OneStar": [
                "Terrible product! Do not buy this."
        ]
    },
    "Comment": "This product sells out quickly during the summer",
    "Safety.Warning": "Always wear a helmet"
 }

CLIで、--projection-expression を指定して実行する。

aws dynamodb get-item \
    --table-name ProductCatalog \
    --key file://key.json \
    --projection-expression "Description, RelatedItems[0], ProductReviews.FiveStar"

★の部分のみ取得できる。

{
    "Item": {
        "Description": {
            "S": "123 description"
        },
        "ProductReviews": {
            "M": {
                "FiveStar": {
                    "L": [
                        {
                            "S": "Excellent! Can't recommend it highly enough! Buy it!"
                        },
                        {
                            "S": "Do yourself a favor and buy this."
                        }
                    ]
                }
            }
        },
        "RelatedItems": {
            "L": [
                {
                    "N": "341"
                }
            ]
        }
    }
}

権限制御に使う(属性レベル制御)

repost.aws

こんなテーブルがあったとする。※上の例とは違うので注意。

GameScoresテーブルの情報がここしかなかった。ドキュメントやサポート回答で利用されるテーブル情報がまとまってるなら欲しい。。。

docs.aws.amazon.com

以下のポリシーでは、WinsLosses は見れないようになっている。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "LimitAccessToSpecificAttributes",
            "Effect": "Allow",
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:Query",
                "dynamodb:BatchGetItem",
                "dynamodb:Scan",
                "dynamodb:TransactGetItems"
            ],
            "Resource": [
                "arn:aws:dynamodb:eu-west-1:123456789012:table/GameScores"
            ],
            "Condition": {
                "ForAllValues:StringEquals": {
                    "dynamodb:Attributes": [
                        "TopScoreDateTime",
                        "TopScore",
                        "UserId",
                        "GameTitle"
                    ]
                },
                "StringEquals": {
                    "dynamodb:Select": "SPECIFIC_ATTRIBUTES"
                }
            }
        }
    ]
}

CLIの例は以下。

# 全部の属性を取得しようとするため AccessDeniedException
aws dynamodb query --table-name GameScores --key-condition-expression "UserId = :useridval" --expression-attribute-values '{":useridval":{"S":"stefano_123"}}'
# Query 成功
aws dynamodb query --table-name GameScores --key-condition-expression "UserId = :useridval" --expression-attribute-values '{":useridval":{"S":"stefano_123"}}' --projection-expression "TopScore, TopScoreDateTime, GameTitle"
# GetItem 成功
aws dynamodb get-item --table-name GameScores --key '{"UserId":{"S":"stefano_123"},"GameTitle":{"S":"Game Zero"}}' --projection-expression "UserId, GameTitle, TopScore, TopScoreDateTime"

ユースケース

で、どんな時にこんな使い方できるのかな?とちょっと考えてみた。たぶん、「ゲームランキング一覧生成のために全員分のデータを取得する必要はあるが詳細な情報は取得しないようにしたい」みたいなケースかな。

となると、項目レベルの制御で「自分のレコードは全部読めるけど、他人のレコードは概要情報だけ」みたいな制御がしたくなってくる。

項目レベルの制御はここら辺に詳しく書いてあるが、詳細は必要になったら読もう。

docs.aws.amazon.com

docs.aws.amazon.com