AWS CloudHSM
AWS CloudHSMは、業界標準のAPIや規格に準拠したクラウドベースのハードウェアセキュリティモジュールで、これを用いることでクラウドで安全に 暗号化キーを生成、保管 できる。AWSのサービスの中では、AWS KMS(Key Management Service)と似た機能を有するが、CLoudHSMはシングルテナント構成で、共通鍵だけでなく 秘密鍵も保管できる 。また、AWS KMSのCMK(カスタマーキー)をCloudHSMで保管することも可能である。
AWS CloudHSMは、業界標準のAPIや規格に準拠したクラウドベースのハードウェアセキュリティモジュールで、これを用いることでクラウドで安全に 暗号化キーを生成、保管 できる。AWSのサービスの中では、AWS KMS(Key Management Service)と似た機能を有するが、CLoudHSMはシングルテナント構成で、共通鍵だけでなく 秘密鍵も保管できる 。また、AWS KMSのCMK(カスタマーキー)をCloudHSMで保管することも可能である。
AWS RAMを利用すると、プロビジョニングもしくは管理されたリソースを 他のAWSアカウントと共有することができる 。サポートしてるAWSリソースは以下の通り。
Organaizations内のアカウント間でこれらのリソースを共有する場合は、invitationは送信されない 。EC2リソースを共有する場合、アカウント毎に同一リージョンのアベイラビリティゾーンの名称が異なる可能性がある。このため、正確にリソースの場所を特定するためには、 AZ ID を使用する。
AWS Organizationsは、 複数のAWSアカウントを統合 するためのアカウント管理サービス。アカウント管理1や 一括請求 機能をはじめとした、以下の機能が備わっている。
これらの機能を実現するために、AWS Organizationsは以下のAWSサービスと連携している。
サービス名 | 有効化 | 実現できること |
---|---|---|
AWS IAM | 不要 | サービスアクティビティ による 最終アクセス時間の確認 |
AWS Artifact | 必要 | 組織契約 による 契約の受諾 |
AWS CloudTrail | 必要 | 組織の証跡 による 証跡の組織への適用 |
AWS CloudWatch Events | 不要 | |
AWS Config | 必要 | アグリゲータ による 集約ビュー の表示 |
AWS Control Tower | 不要 | |
AWS Directory Service | 必要 | |
AWS Firewall Manager | 必要 | AWS Firewall Manager による WAFルールの管理 |
AWS ライセンスマネージャー | 必要 | |
AWS RAM | 必要 | |
AWS Service catalog | 必要 | |
Service Quotas | 不要 | |
AWS シングルサインオン | 必要 | |
AWS System Manager | 必要 | Systems Manager Explorer によるデータの同期 |
タグポリシー | 必要 |
AWS Organizationsを有効化すると、複数のAWSアカウントを一括管理することができる。それぞれのアカウントは、ルートを親として 組織単位 (OU)ごとに分類することができる。アカウントは、 マスターアカウント (=ルート)と メンバーアカウント に分かれ、マスターアカウントにはメンバーアカウントを管理するための様々な権限が付与される。AWS Organizationsの全ての機能を有効化することも、 一括請求機能のみを有効化 することもできる。各OUもしくはアカウント単位に、 サービスコントロールポリシー と呼ばれる各アカウントが持つ権限を明示したポリシーを適用することができる。 サービスコントロールポリシーとタグポリシーは、デフォルトでは無効化されている ので、利用する場合は有効化する。
AWS Organizationsが持つことのできるマスターアカウントは1つのみである。マスターアカウントでOrganizationsを有効化し、その後参加するアカウントを招待することで、メンバーアカウントを追加することができる。 マスターアカウントはサービスコントロールポリシーの影響を受けない 。Organizationsを削除すると復元できず、またポリシーも削除される。削除する際には、 全てのメンバーアカウントを消去する必要 がある。
Organizationsに参加したメンバーアカウントでは、サービスコントロールポリシーやタグポリシーが即座に適用され、またサービスの信頼を有効化している場合は、そのサービスからメンバーアカウントに対してアクションを実行することが許可される。また、Organizations内で新規のメンバーアカウントを作成することもできる。
サービスポリシーは、 最大で使用できるアクセスの権限を各アカウントに対して指定できる機能 。アカウントのルートユーザにも適用され、アカウントに与える影響が非常に大きいため適用する際には詳細のテストが必要である。IAMのサービスアクティビティに表示される、各アカウントの最終アクセス時刻を参考にポリシーの内容を決定することが望ましい。
サービスポリシーは以下のタスクには影響しない。
サービスポリシーは、IAMポリシーとほぼ同じ構文を使用する。複数のポリシーが適用されている場合は、明示的なDenyがAllowよりも優先される。ポリシーの例は、 サービスコントロールポリシーの例 を参照のこと。
タグポリシーを用いることで、タグキーおよびタグ値の大文字と小文字の処理方法の設定などを規定することができる。デフォルトでは、タグポリシーへのコンプライアンスの強制はされない。強制をサポートするAWSサービスは 強制をサポートするサービスとリソースタイプ を参照のこと。
AWS Shieldは、 DDoS攻撃 に対する保護を行う。 AWS Shield Standard
は、追加料金なしで全てのユーザが使用できるサービスで、ウェブサイトやアプリケーションを標的とする、一般的かつ頻繁に発生するネットワークおよび転送レイヤーの DDoS 攻撃を防御する。
AWS Shield Advanced
は、Amazon Elastic Compute Cloud、Elastic Load Balancing (ELB)、Amazon CloudFront、Amazon Route 53、AWS Global Acceleratorなどに対して行われる 高度な攻撃に対応する拡張保護を提供する 。AWS Shield Advanced を利用中にDDoS攻撃を受けた際には、 DDoS response team (DRT) にサポートを依頼できる。また、AWS Shield Advancedには、 AWS WAFが無償で付帯 されている。なお、DRTのサポートを受けるためには、 ビジネスサポートプラン以上の契約 が必要である。
多くの場合は、 AWS Shield Standard
のみで対処可能である。
DDoS攻撃は、一般的に以下のようなタイプに分類される。 AWS Shield Advanced は、これらのDDoS攻撃にも対応可能である。
名称 | 内容 |
---|---|
UDP反射型攻撃 | リクエストの発生元を偽装し、UDP を使用してサーバーから大量のレスポンスを引き出す |
SYN フラッド | 接続を半開状態にして、システムの利用可能なリソースを枯渇させる |
DNS クエリフラッド | DNS クエリを使用して DNS サーバーのリソースを枯渇させる |
レイヤー 7攻撃 | ウェブアプリケーションの実際のユーザーからのように見せかけて多数の HTTP リクエストを送信する |
AWS WAFは、Amazon API Gateway
、Amazon CloudFront
、Application Load Balancer
に転送される HTTP および HTTPS リクエストをモニタリングできるWAF。
ことができる。これらを設定する際には、
などを条件として指定できる。また、 DDoS攻撃の影響を最小限に抑えることが可能な AWS Shield
と組み合わせて使用することもでき、これらのサービスを簡単に管理可能な AWS Firewall Manager
が用意されている。WAFは、ルールの複雑性が加味された Web ACl Capacity Unit 単位で課金される。
CloudFrontと併用する際には、WAFが返却したレスポンスに応じてカスタムエラーページを表示 したり、 CloudFrontの地理的ブロッキング機能と同時に使用する ことができる。
Web ACLは、表示された リスト順に評価 され、ルールに一致するリクエストを 許可 , ブロック , カウント することができる。また、どのルールにも一致しないリクエストをどのように処理するかを定める デフォルトアクション を指定することができる。
WEB ACLに追加可能なルールセットである、ルールグループ を規定することができ、あらかじめAWSやベンダーが作成した、マネージドルールグループ を使用/購入することもできる。ルールグループにはデフォルトアクションが設定されておらず複数のWEB ACLに同一のルールグループを適用することができる。
グループ名 | WCU | 内容 | 利用シーンと効果 |
---|---|---|---|
Admin protection | 100 | 公開されている管理ページへの外部アクセスをブロックするためのルール | サードパーティーのソフトウェアを実行している場合や、悪意のあるアクターがアプリケーションへの管理アクセスを得るリスクを軽減したい場合 |
Amazon IP reputation list | 25 | ボットやその他の脅威に関連付けられている IP アドレスをブロック | ボットを軽減したい場合 |
Core rule set | 700 | ウェブアプリケーションに一般的に適用可能なルール | |
Known bad inputs | 200 | 脆弱性の悪用または発見に関連するリクエストパターンをブロックするルール | 悪意のあるアクターが脆弱なアプリケーションを発見するリスクを軽減 |
Linux operating system | 200 | Linux 固有の脆弱性の悪用に関連するリクエストパターンをブロック | 攻撃者がアクセスしてはならないファイルの内容を公開したり、コードを実行したりする攻撃を防ぐ |
PHP application | 100 | 安全でない PHP 関数のインジェクションなど、PHP プログラミング言語の使用に固有の脆弱性の悪用に関連するリクエストパターンをブロックするルール | 攻撃者が許可されていないコードまたはコマンドをリモートで実行できる脆弱性の悪用を防ぐ |
POSIX operating system | 100 | POSIX および POSIX と同等のオペレーティングシステムに固有の脆弱性の悪用に関連するリクエストパターンをブロックするルール | アクセスしてはならないファイルの内容を公開したり、コードを実行したりする攻撃を防ぐ |
SQL database | 200 | SQL Database ルールグループには、SQL インジェクション攻撃などの SQL データベースの悪用に関連するリクエストパターンをブロックするルール | 不正なクエリのリモートインジェクションを防ぐ |
Windows operating system | 200 | PowerShell コマンドのリモート実行など、Windows 固有の脆弱性の悪用に関連するリクエストパターンをブロックするルール | 悪意のあるコードを実行したりする脆弱性の悪用を防ぐ |
WordPress application | 100 | WordPress サイト固有の脆弱性の悪用に関連するリクエストパターンをブロックするルール |
ログ記録を有効化することで、WEB ACLで分析されるトラフィックの詳細情報を取得することができる。ログ記録を有効化すると Kinesis Firehose経由で指定した場所にログが保存される 。
また、CloudWatchアラームで特定のメトリクスをモニタリング することができるほか、CloudTrailによるアクションレコードの保存にも対応している。
FireWall Managerを用いることで、AWS WAF Classic ルール、AWS Shield アドバンスド 保護、 Amazon VPC セキュリティグループ を有効化することができ、これにより組織全体の保護を行ったり、リソースの頻繁な追加に対応し、組織全体のDDoS攻撃を一元的に監視することができる。 FireWall Managerを使用するためには、AWS Organizationのメンバーである必要 がある。
AWS CloudFormationは、AWSのリソースのモデル化およびセットアップを行うことができるサービスで、テンプレートを作成すれば、CloudFormationがこのテンプレートに沿ってリソースのプロビジョニング等を行う。CloudFormationを使用することで以下のようなメリットが生じる。
CloudFormationの テンプレート はAWSリソースを作成する際の設計図の機能を持ち、JSONもしくはYAML形式で記述することができる。YAML形式のみコメント機能が使用できる。このテンプレートを元にプロビジョニングされたAWSリソースは、スタック と呼ばれる単一ユニットとして管理される。スタックは、作成や変更、削除が可能で、変更時には変更概要を示した 変更セット が作成される。変更前に変更セットを確認することで、この変更がリソースに与える影響を事前に検証することができる。
CloudFormationはCloudTrail
と統合されており、CloudFormation内でのアクションをログに記録する。
CloudFormationを実行する際にリソースタグを付与することができるが、当該スタックに含まれるリソース全てに対してこのタグが伝搬する訳ではない。また、リソースによってはリソースタグの付与自体ができないことに注意が必要である。
入力パラメータ、マッピングなど、テンプレート内部で使用するパラメータの数には上限値が存在する。また、テンプレート自体のファイルサイズの上限も存在するため、上限を超過する場合には、S3バケットに対して事前にテンプレートをアップロードする か、 複数のネステッドスタックにテンプレートを分割 する必要がある。
CloudFormationが作成できるAWSリソースは、CloudFormationを実行したユーザが持つアクセス権限に含まれるもののみ である。もしくは、AWS CloudFormation サービスロール
と呼ばれるCloudFormationにリソースの作成や更新、削除を許可するIAMロールを割り当てることもできる。なお、特定の機能が含まれるテンプレートについては、実行時に以下を了承する必要がある。
機能 | 内容 |
---|---|
CAPABILITY_IAM | IAMリソースが含まれている場合 |
CAPABILITY_NAMED_IAM | 自身で命名したIAMリソースが含まれている場合 |
CAPABILITY_RESOURCE_POLICY | リソースポリシーが含まれている場合 |
CAPABILITY_AUTO_EXPAND | ネストされたアプリケーションが含まれている場合 |
IAMロールでは、リソースタイプやテンプレートURLなどを 限定 して、CloudFormationスタックの作成や削除を許可したり拒否したりすることもできる。
CloudFormationテンプレートには、作成や設定したいAWSリソースを宣言することができ、以下のセクションが用意されている。
セクションタイプ | 設定内容 |
---|---|
AWSTemplateFormatVersion | 形式バージョン |
Conditions | 制御条件 |
Description | テンプレートを説明するテキスト文字列, AWSTemplateFormatVersionの後に記述する |
Mappings | プロビジョニング先のリージョンなどの条件に合わせて参照先が変更可能なパラメータ |
Metadata | 追加情報, AWS::CloudFormation::Designerはデザイナーのレイアウト情報を含む |
Outputs | 出力パラメータ |
Parameters | 入力パラメータ |
Resources | AWSリソースの指定 |
Transform | テンプレートを処理するマクロを指定 |
設定変更するプロパティによっては、既存のリソースに影響が発生する可能性がある。例えば、アップデート中に リソースが一旦停止 する場合や、変更自体ができないリソースも存在 する。
Parameters
セクションで入力パラメータを定義することができ、入力パラメータを指定してテンプレートを実行することで、 各種パラメータをカスタマイズ することができる。デフォルト値を持つ入力パラメータは、ユーザが別の値を入力しない限りデフォルト値が適用される。一方で、プロビジョニング済みのリソースで、かつマネージメントコンソールから操作をする場合は、ユーザが別の値を入力しない限り 現在の設定値が適用 される。入力パラメータには、以下の項目で値に制約を与えることができる。
指定できるパラメータのデータ型は、String
, Number
, List<Number>
, CommaDelimitedList
, AWS 固有のパラメーター型
, SSM パラメータータイプ
の6タイプがサポートされている。機密データには、 NoEcho
属性を指定するとよい。
型 | 制約タイプ |
---|---|
String | MinLength, MaxLength, Default, AllowedValues, AllowedPattern |
Number | MinValue, MaxValue, Default, AllowedValues |
Mappings
セクションは、キーと名前付き一連データとかが対応付けられる。これを用いることで、リージョンごとに異なるリソースの設定値を一括して管理することができる。これらの値は、FindInMap
関数で取得することができる。
Mappings
セクションでは、リソースを設定するか否かを判定する条件を定義することができ、この値が true
の場合のみ、当該のリソースを作成することができる。なお、スタック更新時に、Conditions のみを単独で更新することはできず 、リソースの追加や変更などが存在する場合に、 Conditions も再評価される。
Resources
セクションでは、スタックに含めるAWSリソースを宣言する。conditionsセクションと組み合わせることで、条件付きでリソースを作成 できる。
他のスタックにインポートする値、もしくはCloudFormationコンソールに表示する出力値を宣言する。 Exports
属性を追加して、 クロススタック参照 に対応することもできる。
Resources
にリソース属性 を指定することで、リソースの追加や削除の際の挙動を制御することができる。
指定数の成功シグナルやタイムアウトが過ぎるまでは作成完了とならないようにする
プロパティ | 内容 |
---|---|
AutoScalingCreationPolicy | いくつのインスタンスが成功すると更新を続行するか |
ResourceSignal | 関連リソースを作成する際に必要なシグナル数 |
スタックが削除されたときやリソースを置き換える際の動作を規定する。スナップショットが有効なリソースは、EC2ボリューム 、 Elasticache 、 Neptureクラスタ 、 RDSクラスタ/インスタンス 、Redshiftクラスタ である。
プロパティ | 内容 |
---|---|
Delete | 削除する( DBクラスタ以外のデフォルト ) |
Retain | スタックを削除してもリソースを削除しない |
Snapshot | 削除する前にスナップショットを作成する(DBクラスタのデフォルト) |
AutoScalingGroup、Lambdaエイリアス、ElastiCacheレプリケーショングループの更新方法を指定する。
他のリソースに続けて作成されるように指定する。 Ref関数でリソースを参照する場合などは、暗黙的に依存関係が構築されるので記述の必要はない 。
構造化データを関連づける。
CloudFormationには、スタックの管理に役立つ組み込み関数があらかじめ用意されている。
関数名 | 実行内容 |
---|---|
Fn::Base64 | Base64エンコード |
Fn::Cidr | CIDR アドレスブロックの配列を返す |
Fn::FindInMap | Mappings セクションから値を返す |
Fn::GetAtt | 属性の値を返す |
Fn::GetAZs | 指定されたリージョンのアベイラビリティーゾーンを含んだ配列を返す |
Fn::ImportValue | 別のスタックの出力値を返す |
Fn::Join | 複数の値を連結する |
Fn::Select | リストから1つのオブジェクトを返す |
Fn::Split | 文字列を分割する |
Fn::Sub | 変数を文字列に組み込む |
Fn::Transform | テンプレートをカスタム処理するマクロを指定する |
Ref | 指定したパラメータまたはリソースの値を返す |
Fn::Sub
や Ref
で取得した値に対して四則演算等を行うことはできない。また、CloudFormationテンプレートのキー値に対して、 Fn::Sub
や Ref
などを用いて値を代入することもできないl。
条件付きでリソースを作成する場合に使用する。Fn::If以外は、Conditions
セクションで使用する。
関数名 | 相当する演算子 |
---|---|
Fn::And | and |
Fn::Equals | == |
Fn::If | if |
Fn::Not | != |
Fn::Or | or |
擬似パラメータと呼ばれる事前に定義されたパラメータを使用することができる。
パラメータ名 | 内容 |
---|---|
AWS::AccountId | スタックが作成されているアカウントの AWS アカウント ID |
AWS::NotificationARNs | 現在のスタックの通知 Amazon リソースネーム (ARN) のリスト |
AWS::NoValue | 指定なし |
AWS::Partition | AWSパーティション |
AWS::Region | AWSリージョン |
AWS::StackId | スタックID |
AWS::StackName | スタック名 |
AWS::URLSuffix | ドメインのサフィックス |
AWS SAMは、サーバレスアプリケーションを構築するための オープンソース フレームワークであり、数行の設定のみで、必要なアプリケーションを定義できる。AWS SAMは、CloudFormation拡張テンプレート仕様 および AWS SAM CLI コンポーネントから構成される。
AWS SAMを使用することで、関連するコンポーネントとリソースの整理、操作が単一のスタックで管理できる。また、メモリやタイムアウト値などの設定値をリソース間で共有することも可能である。また、CloudFormationの拡張機能 であるため、 CloudFormationに対応するリソースと組み合わせてリソースを管理することができる。
AWS SAMには、ローカルの開発環境でLambda実行環境と同等の機能を提供する。これを用いることで、AWS上にデプロイする前に、ローカルの開発環境で動作や問題等を確認することができる。
また、Lambdaを安全にデプロイするために、 一定期間の間に段階的に新しいバージョンをデプロイすることも可能 である。
プロジェクト名として指定したディレクトリの下に、sam-app
ディレクトリと、SAMプロジェクトおよびサンプルテンプレートを作成する。
SAMテンプレートが有効であるかどうか検証する。AWS CLI Configureにてデフォルトリージョンを設定していない場合には、以下のように環境変数を与える必要がある。
env AWS_DEFAULT_REGION=ap-northeast-1 sam validate
sam-app
ディレクトリ直下に .aws-sam
を作成し、この下に、指定した実行環境をターゲットとする デプロイメントアーティファクト を作成する。例えば、LambdaをPythonで記述した場合に、 requirements.txt
にて依存関係のあるライブラリを指定することができるが、 sam build
はこれらの依存関係を適切に処理する。
デプロイメントアーティファクト を圧縮してS3にアップロードする。また、パッケージ化されたSAMテンプレート(packaged.yaml
)を作成する。パッケージ化されたSAMテンプレートには、S3にアップロードした デプロイメントアーティファクト へのリンク先が記述されている。sam deploy
コマンドは、 sam package
コマンドを暗黙的に実行するため、本来は sam deploy
コマンドを実行するだけでよい。
アプリケーションのデプロイを行う。 --guided
パラメータを付与することで、インタラクティブモードを起動することができる。
Lambdaが生成するログを確認することができる。
SAMテンプレートには、 Globals
セクションが設けられており、ランタイムやメモリなどの共通設定をこれに格納することができる。なお、以下のプロパティはサポートされていない。
Function:
Role:
Policies:
FunctionName:
Events:
Api:
StageName:
DefinitionBody:
SAMテンプレートでは、以下のリソースタイプがサポートされている。AWS :: Serverless :: LayerVersion
のみ DeletionPolicy
をサポートしている。また、 AWS :: Serverless :: Api
内で記述するOpenAPIドキュメントは、 一部のAPI Gateway拡張(x-amazon-apigateway-) のみサポートしていることに注意が必要である。
タイプ | 作成されるリソース | 備考 |
---|---|---|
AWS :: Serverless :: Api | API Gateway | OpenAPIを使用してAPIを定義する |
AWS :: Serverless :: Application | SAM | Serverless Application Repositoryのリソースをデプロイ可能 |
AWS :: Serverless :: Function | Lambda, IAM Role | |
AWS :: Serverless :: HttpApi | API Gateway Http Api | |
AWS :: Serverless :: LayerVersion | Lambda Layer Version | |
AWS :: Serverless :: SimpleTable | DynamoDB | プライマリキーのみのテーブルを作成 |
SAMでは、Lambdaのアクセス許可をポリシーテンプレートという形で指定することができる。ポリシーテンプレートは、あらかじめAWSが用意したポリシーパターンである。
sam local
コマンドを用いることでローカルで、API GatewayやLambdaを実行させることができ、開発環境でアプリケーションの動作を検証することができる。
CIS AWS Foundations Benchmark というセキュリティガイドラインが公開されており、このガイドラインは、AWSアカウントをセキュアに保つために必要なAWSのセキュリティ設定を集めたベストプラクティス集として活用できる。
この CIS AWS Foundations Benchmark
では、CloudTrailによって検知された特定のイベントに対して以下のような対応を求めている。
上述のログメトリクスフィルタとアラームを設定し、CIS AWS Foundations Benchmark
に 準拠するために以下の設定を行う。
Resources:
# CIS 3.1 a log metric filter and alarm exist for unauthorized API calls
CloudWatchLogsMetricFilterCloudTrailUnauthorizedAPICalls:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.errorCode="*UnauthorizedOperation") || ($.errorCode="AccessDenied*")}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: UnauthorizedAPICalls
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailUnauthorizedAPICalls:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *不正なAPIコールを検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-Unauthorized-API-Calls'
ComparisonOperator: GreaterThanOrEqualToThreshold
DatapointsToAlarm: 6
EvaluationPeriods: 60
MetricName: UnauthorizedAPICalls
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.2 a log metric filter and alarm exist for AWS Management Console sign-in without MFA
CloudWatchLogsMetricFilterCloudTrailLoginWithoutMFA:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName="ConsoleLogin") && ($.additionalEventData.MFAUsed !="Yes")}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: LoginWithoutMFA
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailLoginWithoutMFA:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *MFAなしのログインを検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-Login-Without-MFA'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: LoginWithoutMFA
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.3 a log metric filter and alarm exist for usage of "root" account
CloudWatchLogsMetricFilterCloudTrailForRootAcount:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{$.userIdentity.type="Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType !="AwsServiceEvent"}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: ForRootAcount
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailForRootAcount:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *ルートアカウントに対する変更を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-For-RootAcount'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: ForRootAcount
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.4 a log metric filter and alarm exist for IAM policy changes
CloudWatchLogsMetricFilterCloudTrailIamPolicyChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=DeleteGroupPolicy) || ($.eventName=DeleteRolePolicy) || ($.eventName=DeleteUserPolicy) || ($.eventName=PutGroupPolicy) || ($.eventName=PutRolePolicy) || ($.eventName=PutUserPolicy) || ($.eventName=CreatePolicy) || ($.eventName=DeletePolicy) || ($.eventName=CreatePolicyVersion) || ($.eventName=DeletePolicyVersion) || ($.eventName=AttachRolePolicy) || ($.eventName=DetachRolePolicy) || ($.eventName=AttachUserPolicy) || ($.eventName=DetachUserPolicy) || ($.eventName=AttachGroupPolicy) || ($.eventName=DetachGroupPolicy)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: IamPolicyChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailIamPolicyChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *IAMポリシーの変更を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-IamPolicy-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: IamPolicyChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.5 a log metric filter and alarm exist for CloudTrail configuration changes
CloudWatchLogsMetricFilterCloudTrailCloudTrailConfigurationChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=CreateTrail) || ($.eventName=UpdateTrail) || ($.eventName=DeleteTrail) || ($.eventName=StartLogging) || ($.eventName=StopLogging)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: CloudTrailConfigurationChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailCloudTrailConfigurationChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *CloudTrailの設定変更を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-CloudTrailConfiguration-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: CloudTrailConfigurationChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.6 a log metric filter and alarm exist for AWS Management Console authentication failures
CloudWatchLogsMetricFilterCloudTrailAuthenticationFailuresDetected:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=ConsoleLogin) && ($.errorMessage="Failed authentication")}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: AuthenticationFailuresDetected
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailAuthenticationFailuresDetected:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *ログイン認証失敗を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-AuthenticationFailures-Detected'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: AuthenticationFailuresDetected
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.7 a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs
CloudWatchLogsMetricFilterCloudTrailCustomerCreatedCMKsChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventSource=kms.amazonaws.com) && (($.eventName=DisableKey) || ($.eventName=ScheduleKeyDeletion))}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: CustomerCreatedCMKsChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailCustomerCreatedCMKsChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *カスタマー作成CMKの無効化もしくは削除を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-CustomerCreatedCMKs-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: CustomerCreatedCMKsChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.8 a log metric filter and alarm exist for S3 bucket policy changes
CloudWatchLogsMetricFilterCloudTrailS3BucketPolicyChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventSource=s3.amazonaws.com) && (($.eventName=PutBucketAcl) || ($.eventName=PutBucketPolicy) || ($.eventName=PutBucketCors) || ($.eventName=PutBucketLifecycle) || ($.eventName=PutBucketReplication) || ($.eventName=DeleteBucketPolicy) || ($.eventName=DeleteBucketCors) || ($.eventName=DeleteBucketLifecycle) || ($.eventName=DeleteBucketReplication))}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: S3BucketPolicyChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailS3BucketPolicyChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *S3のバケットポリシーの変更を検知* しました。'
AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-S3BucketPolicy-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: S3BucketPolicyChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.9 a log metric filter and alarm exist for AWS Config configuration changes
CloudWatchLogsMetricFilterCloudTrailConfigConfigurationChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventSource=config.amazonaws.com) && (($.eventName=StopConfigurationRecorder) || ($.eventName=DeleteDeliveryChannel) || ($.eventName=PutDeliveryChannel) || ($.eventName=PutConfigurationRecorder))}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: ConfigConfigurationChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailConfigConfigurationChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *Configの設定変更を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-ConfigConfiguration-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: ConfigConfigurationChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.10 a log metric filter and alarm exist for changes to Security Group
CloudWatchLogsMetricFilterCloudTrailSecurityGroupChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=AuthorizeSecurityGroupIngress) || ($.eventName=AuthorizeSecurityGroupEgress) || ($.eventName=RevokeSecurityGroupIngress) || ($.eventName=RevokeSecurityGroupEgress) || ($.eventName=CreateSecurityGroup) || ($.eventName=DeleteSecurityGroup)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: SecurityGroupChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailSecurityGroupChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *セキュリティグループの変更を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-SecurityGroup-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: SecurityGroupChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.11 a log metric filter and alarm exist for changes to Network Access Control Lists (NACL)
CloudWatchLogsMetricFilterCloudTrailNACLChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=CreateNetworkAcl) || ($.eventName=CreateNetworkAclEntry) || ($.eventName=DeleteNetworkAcl) || ($.eventName=DeleteNetworkAclEntry) || ($.eventName=ReplaceNetworkAclEntry) || ($.eventName=ReplaceNetworkAclAssociation)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: NACLChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailNACLChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *NACLの変更を検知* しました。'
AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-NACL-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: NACLChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.12 a log metric filter and alarm exist for changes to network gateways
CloudWatchLogsMetricFilterCloudTrailNetworkGatewayChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=CreateCustomerGateway) || ($.eventName=DeleteCustomerGateway) || ($.eventName=AttachInternetGateway) || ($.eventName=CreateInternetGateway) || ($.eventName=DeleteInternetGateway) || ($.eventName=DetachInternetGateway)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: NetworkGatewayChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailNetworkGatewayChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *ネットワークゲートウェイの変更を検知* しました。'
AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-NetworkGateway-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: NetworkGatewayChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.13 a log metric filter and alarm exist for route table changes
CloudWatchLogsMetricFilterCloudTrailRouteTableChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=CreateRoute) || ($.eventName=CreateRouteTable) || ($.eventName=ReplaceRoute) || ($.eventName=ReplaceRouteTableAssociation) || ($.eventName=DeleteRouteTable) || ($.eventName=DeleteRoute) || ($.eventName=DisassociateRouteTable)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: RouteTableChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailRouteTableChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *ルートテーブルの変更を検知* しました。'
AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-RouteTable-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: RouteTableChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.14 a log metric filter and alarm exist for VPC changes
CloudWatchLogsMetricFilterCloudTrailVpcChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=CreateVpc) || ($.eventName=DeleteVpc) || ($.eventName=ModifyVpcAttribute) || ($.eventName=AcceptVpcPeeringConnection) || ($.eventName=CreateVpcPeeringConnection) || ($.eventName=DeleteVpcPeeringConnection) || ($.eventName=RejectVpcPeeringConnection) || ($.eventName=AttachClassicLinkVpc) || ($.eventName=DetachClassicLinkVpc) || ($.eventName=DisableVpcClassicLink) || ($.eventName=EnableVpcClassicLink)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: VpcChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailVpcChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *VPCの変更を検知* しました。'
AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-Vpc-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: VpcChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
また、これらのメトリクスのアラーム通知先となる、Amazon SNS
と Topic Policy
を作成する。
Resources:
SNSAlert:
Type: 'AWS::SNS::Topic'
Properties:
DisplayName: !Sub 'System Notifications from ${AWS::StackName}'
TopicName: !Sub '${AWS::StackName}-system-notifications'
SNSAlertTopicPolicy:
Type: 'AWS::SNS::TopicPolicy'
Properties:
Topics:
- !Ref SNSAlert
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
# All AWS Services
Principal:
AWS: '*'
Resource: '*'
Action: 'SNS:Publish'
CIS AWS Foundations Benchmark というセキュリティガイドラインが公開されており、このガイドラインは、AWSアカウントをセキュアに保つために必要なAWSのセキュリティ設定を集めたベストプラクティス集として活用できる。
この CIS AWS Foundations Benchmark
では、デフォルトセキュリティグループについて、以下の設定とすることが奨励されている。
この CIS AWS Foundations Benchmark
に 準拠していないデフォルトセキュリティグループ を SSM Automation
を用いて 自動修復 するために以下の設定を行う。
AWS Config
を用いて定期的にチェックを行うAWS Config
が SSM Automation
を自動起動するSSM Automation
が非準拠のデフォルトセキュリティグループの設定を自動修復するAWS Config
を有効化する手順については、こちら。
デフォルトセキュリティグループ設定のチェックには、あらかじめAWS Config
に用意されている vpc-default-security-group-closed
マネージドルールを使用する。デフォルトセキュリティグループがこの条件を満たしていない場合、このリソースはルールに 非準拠(NON_COMPLIANT) であると判定される。
なお、この Config Rule
を設定する前に ConfigurationRecorder
を生成しておく必要がある。そこで、DependsOn
属性に ConfigurationRecorder
リソースを設定している。
Resources:
ConfigVpcDefaultSecurityGroupClosed:
DependsOn:
- ConfigConfigurationRecorder
Type: 'AWS::Config::ConfigRule'
Properties:
ConfigRuleName: vpc-default-security-group-closed
Description: いずれの Amazon Virtual Private Cloud (VPC) のデフォルトのセキュリティグループでもインバウンドとアウトバウンドのいずれのトラフィックも許可しないことを確認します。
Source:
Owner: AWS
SourceIdentifier: VPC_DEFAULT_SECURITY_GROUP_CLOSED
Systems Manager Automation
は、AWS Config
で 直接指定できる、現時点で唯一の自動修復手段 となっている。そこで、デフォルトのセキュリティグループを修復する Systems Manager Automation
ドキュメント を作成し、AWS Config
との紐付けを行う。
下のSystems Manager Automation
ドキュメントは、EC2
の RevokeSecurityGroupIngress
, RevokeSecurityGroupEgress
, DescribeSecurityGroups
を実行して、デフォルトセキュリティグループの設定を自動修復する。
Resources:
SSMAutomationRevokeDefaultSecurityGroup:
Type: 'AWS::SSM::Document'
Properties:
Content:
schemaVersion: "0.3"
assumeRole: "{{ AutomationAssumeRole }}"
description: Revoke Default Security Group.
mainSteps:
- name: DescribeSecurityGroups
action: aws:executeAwsApi
onFailure: Abort
inputs:
Service: ec2
Api: DescribeSecurityGroups
GroupIds: ["{{ GroupId }}"]
outputs:
- Name: IpPermissionsIngress
Selector: $.SecurityGroups[0].IpPermissions
Type: MapList
- Name: IpPermissionsEgress
Selector: $.SecurityGroups[0].IpPermissionsEgress
Type: MapList
- name: RevokeSecurityGroupIngress
action: aws:executeAwsApi
onFailure: Continue
inputs:
Service: ec2
Api: RevokeSecurityGroupIngress
GroupId: "{{ GroupId }}"
IpPermissions: "{{ DescribeSecurityGroups.IpPermissionsIngress }}"
- name: RevokeSecurityGroupEgress
action: aws:executeAwsApi
onFailure: Continue
inputs:
Service: ec2
Api: RevokeSecurityGroupEgress
GroupId: "{{ GroupId }}"
IpPermissions: "{{ DescribeSecurityGroups.IpPermissionsEgress }}"
parameters:
AutomationAssumeRole:
type: String
description: Automation Assume Role Arn
GroupId:
type: String
description: Group Id
DocumentType: Automation
Systems Manager Automation
ドキュメントは、上述の通り IAM
の RevokeSecurityGroupIngress
などを実行する必要があるため、このAWS API アクションを Systems Manager Automation
から呼び出すことを可能とする IAM Role を作成する。
Resources:
IAMRoleForSSM:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: ssm.amazonaws.com
Action: 'sts:AssumeRole'
Description: A role required for SSM to access IAM.
Policies:
- PolicyName: !Sub '${PrefixOfLogicalName}-AWSSystemManagerIAMRole-${AWS::Region}'
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- 'ec2:RevokeSecurityGroupIngress'
- 'ec2:RevokeSecurityGroupEgress'
- 'ec2:DescribeSecurityGroups'
Resource:
- '*'
RoleName: !Sub '${AWS::StackName}-SSM-${AWS::Region}'
このIAM RoleのARNは、AWS Config
から Systems Manager Automation
へ渡されるパラメータの1つとして規定される。AWS::Config::RemediationConfiguration
は、非準拠(NON_COMPLIANT)と判定された場合の自動修復方法を規定し、Config Rule
と Systems Manager Automation
との紐付けや、受け渡されるパラメータの規定を行う。自動修復を行う場合は、AutomationAssumeRole, MaximumAutomaticAttempts, RetryAttemptSeconds の各パラメータの入力が必須である。
Resources:
ConfigVpcDefaultSecurityGroupClosedRemediationConfiguration:
Condition: CreateRemediationResources
Type: 'AWS::Config::RemediationConfiguration'
Properties:
Automatic: true
ConfigRuleName: !Ref ConfigVpcDefaultSecurityGroupClosed
MaximumAutomaticAttempts: 1
Parameters:
AutomationAssumeRole:
StaticValue:
Values:
- !GetAtt IAMRoleForSSM.Arn
GroupId:
ResourceValue:
Value: RESOURCE_ID
RetryAttemptSeconds: 30
TargetId: !Ref SSMAutomationRevokeDefaultSecurityGroup
TargetType: SSM_DOCUMENT
以上で、デフォルトセキュリティグループからインバウンドおよびアウトバンドの許可ルールを削除することができた。
CIS AWS Foundations Benchmark というセキュリティガイドラインが公開されており、このガイドラインは、AWSアカウントをセキュアに保つために必要なAWSのセキュリティ設定を集めたベストプラクティス集として活用できる。
この CIS AWS Foundations Benchmark
では、EC2/VPCのセキュリティグループについて、以下の設定とすることが奨励されている。
この CIS AWS Foundations Benchmark
に 準拠していないセキュリティグループ を SSM Automation
を用いて 自動修復 するために以下の設定を行う。
AWS Config
を用いて定期的にチェックを行うAWS Config
が SSM Automation
を自動起動するSSM Automation
が奨励されたセキュリティグループ設定となるように設定を自動修復するAWS Config
を有効化する手順については、こちら。
セキュリティグループの設定のチェックには、あらかじめAWS Config
に用意されている vpc-default-security-group-closed
マネージドルールを使用する。セキュリティグループがこの条件を満たしていない場合、このリソースはルールに 非準拠(NON_COMPLIANT) であると判定される。
なお、この Config Rule
を設定する前に ConfigurationRecorder
を生成しておく必要がある。そこで、DependsOn
属性に ConfigurationRecorder
リソースを設定している。
Resources:
ConfigSVpcSgOpenOnlyToAuthorizedPorts:
DependsOn:
- ConfigConfigurationRecorder
Type: 'AWS::Config::ConfigRule'
Properties:
ConfigRuleName: vpc-sg-open-only-to-authorized-ports
Description: いずれかの 0.0.0.0/0 Amazon Virtual Private Cloud (Amazon VPC) を持つセキュリティグループで、特定のインバウンド TCP または UDP トラフィックのみが許可されるかどうかを確認します。
InputParameters:
authorizedTcpPorts: 1-21,23-3388,3390-65535
authorizedUdpPorts: 1-21,23-3388,3390-65535
Source:
Owner: AWS
SourceIdentifier: VPC_SG_OPEN_ONLY_TO_AUTHORIZED_PORTS
Systems Manager Automation
は、AWS Config
で 直接指定できる、現時点で唯一の自動修復手段 となっている。そこで、セキュリティグループ を修復する Systems Manager Automation
ドキュメント と AWS Config
との紐付けを行う。
修復には、あらかじめ用意されている AWS-DisablePublicAccessForSecurityGroup
ドキュメントを使用する。このドキュメントは、すべての IP アドレスに対して開かれているデフォルトの SSH および RDP ポートを無効にする。
Resources:
ConfigVpcSgOpenOnlyToAuthorizedPortsRemediationConfiguration:
Condition: CreateRemediationResources
Type: 'AWS::Config::RemediationConfiguration'
Properties:
# NOTE: AutomationAssumeRole, MaximumAutomaticAttempts and RetryAttemptSeconds are Required if Automatic is true.
Automatic: true
ConfigRuleName: !Ref ConfigSVpcSgOpenOnlyToAuthorizedPorts
MaximumAutomaticAttempts: 1
Parameters:
AutomationAssumeRole:
StaticValue:
Values:
- !GetAtt IAMRoleForSSM.Arn
GroupId:
ResourceValue:
Value: RESOURCE_ID
RetryAttemptSeconds: 30
TargetId: AWS-DisablePublicAccessForSecurityGroup
TargetType: SSM_DOCUMENT
以上で、すべての IP アドレスに対して開かれているデフォルトの SSH および RDP ポートを無効にすることができた。