この回ではAWSでサーバレスなサービスでシステムを構築していく際に抑えておくべきセキュリティ対策のポイントについて解説します。以下の図のようにAWS Lambdaを中心としたサーバレスな構成の場合はアプリケーションレイヤー以上のセキュリティを考慮する必要があります。ここの具体例に合わせて、開発者にもどのような権限を与えながら開発を行っていくべきかについても述べます。
AWS IAMについて
まずはAWSアカウント自体とそのセキュリティのための機能として提供されているAWS IAMの使い方について説明します。AWS Identity and Access Management (IAM) は、AWS 全体できめ細かいアクセス制御を行います。IAM を使用すると、誰がどのサービスやリソースに、どのような条件でアクセスできるかを指定することができます。IAM ポリシーでは、ワークロードやシステムに対するアクセス許可を管理し、最小権限のアクセス許可を確保します。IAMにはアクセス制御のためのたくさんの機能がありますがまずは基本となる以下の3つの機能について説明します。
IAMユーザとグループ
IAMユーザはAWSを使用する個人に割り当てられるアカウントです。AWSのマネジメントコンソールからログインしてAWSサービスを操作したり、AWSCLIやAWSSDKを使用してターミナルやプログラムからAWSサービスを使用するために使われます。
IAMグループは共通の権限をもつIAMユーザをひとまとめにするための機能です。特定の部署に共通の権限を付与する場合は、その部署用に特定のIAMグループを作成し、そこに必要な権限とIAMユーザを紐付けていきます。
IAMポリシー
AWSリソースへの操作権限を設定するための機能です。IAMユーザやグループ、後述するIAMロールにアタッチすることでAWSリソースの操作対象者に操作権限を付与します。それぞれ以下のような種類のポリシーが存在します。
- AWS管理ポリシー
AWSが用途に応じて提供しているポリシーです。ユーザ側で編集等は出来ません。
- カスタマー管理ポリシー
ユーザ側で用途に応じて作成することが出来るポリシーです。必要なインラインポリシーやIPアドレスでの制限など、より細かなアクセス制限を作成して権限を付与することが出来ます。
- インラインポリシー
IAMユーザやIAMロールに直接アタッチして作成するポリシーです。AWS管理ポリシーやカスタマー管理ポリシーが1つのポリシーを複数のIAMにアタッチすることが可能ですが、インラインポリシーは特定のIAMのみにアタッチされます。
IAMロール
AWSサービスやAWSアカウントに対してアクセス権限を制御する仕組みです。AWS Lambdaから他のAWSサービスにアクセスする際にはIAMロールを設定してそこに必要なIAMポリシーをアタッチすることで、アクセス可能となります。
他にも他AWSアカウントから特定のAWSサービスのアクセスを許可したり、IDフェデレーションといって、GoogleやFacebookなどのIDプロバイダーに対してアクセスを許可するようなIAMロールを作成することもできます。
開発用IAMユーザ及びグループに対するセキュリティ
AWSで開発を行う際には開発用のIAMユーザ及びIAMグループを発行して、ローカルでの開発用に開発者に権限を割り当てていきます。その際には以下のようなセキュリティ指針を最低限守るようにしましょう
- IAMユーザを使い回さない
IAMユーザは1開発者につき1つを付与するようにしましょう。そして万一IAMユーザを複数人で使いまわしていたとすると、インシデントが発生した際に原因となる操作がCloudTrailのログから特定できたとしても、誰がそれを行ったのか分からなくなるためです。2024年現在、 IAM ユーザーはどうしても必要な場合を除き、基本的には後述する「AWS IAM Identity Center (AWS SSO)」を利用するようにしてください。
- MFAを有効化する
まず前提としてパスワードを強固にすることは重要です。しかしMFAを有効にしてブルートフォースアタック(総当たり攻撃)からのアカウント乗っ取り被害を確実に防ぐようにしましょう。
- CloudTrailを有効化して操作をロギングする
CloudTrailを有効化することで、AWS上で行われた操作がすべてログとして記録されます。万一、セキュリティインシデントでIAMユーザが乗っ取られてしまったとしてもその操作をすべて追いかけることが出来るので、原因の特定に役立ちます
- 必要最小限の権限に絞る
不用意に大きな権限を付与しないようにしましょう
- 出来る限り固有のアクセスキーを発行しないようにする
アクセスキーが流出して、不正な操作が行われることにより多額のAWS費用が請求されるインシデントはもっともよくやりがちなインシデントの1つです。また、アクセスキーを管理する工数も発生するため、出来る限り発行しないようにしましょう
サーバレスな開発を行う上での実際のところ
サーバレスな開発では様々なAWSのサービスを使用するため、IAMユーザに対しては必要最小限の権限を特定して絞ることが難しくなります。その場合はそれなりに大きな権限のIAMユーザを発行することが多くなります。その際は固有のアクセスキーを発行せずに、有効期限の存在する一時クレデンシャルを以下のサービスを使用して使うことをお勧めします。
- AWS IAM Identity Center (AWS SSO)を使う
複数の AWS アカウントやアプリケーションへのアクセスを一元管理出来るサービスです。これを使うことで、AWSアカウントをまたいで使えるIAMユーザを発行でき、そのクレデンシャルは一時的なものになるため、長期に渡ってローカルマシンに保持されることがありません。
- AWS CLI から AWS STS (Security Token Service) を利用してAssumeRoleを行う
AWSにはAssumeRoleという権限を移譲するための仕組みがあります。AWS CLIからも可能で、ローカル開発時にこの機能を使うことで一時クレデンシャルをローカルで発行できます。
AWSサービスにアタッチするIAMロールに対するセキュリティ
AWSサービス間の操作についても必要最小限の操作のみを許可するようにしましょう。例えばAWS LambdaからAmazon DynamoDBにアクセスする場合にデータの読み取りしか許可しない場合は以下のようなIAMポリシーとなるでしょう。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:Scan",
"dynamodb:GetItem",
"dynamodb:Query"
],
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/YourTableName"
}
]
}
また、AWS Lambdaを中心としたイベントドリブンなアーキテクチャを構築する場合は、各AWSサービスからAWS Lambdaを動かすために必要なIAMロールはIaCツールで自動で付与されることがほとんどです。基本的にはAWS LambdaからアクセスするAWSサービスに絞って必要なIAMポリシーを設計する必要があるでしょう。
アプリケーション側におけるセキュリティ
ここからはIAMでは制御ができないアプリケーション自体に対するセキュリティについて見ていきます。AWSアカウントやリソースに対するセキュリティ対策はAWS IAMで行うことは出来ますが、アプリケーションで定義したユーザデータの流出などに対するセキュリティ対策はAWS IAMで制御することは出来ないため、アプリケーション側で制御する必要が出てきます。例としてECサイトで商品を管理するためのAPIをAmazon API Gateway + AWS Lambda + Amazon DynamoDBで実装したとします
APIの種類 | 仕様 | アクセス制御 |
商品登録API | 商品の登録を行います | ログインユーザのみ可能 |
商品更新API | 指定した商品の情報を更新します | その商品のOwnerのみ可能 |
商品削除API | 指定した商品を削除します | その商品のOwnerのみ可能 |
商品取得API | 登録された商品のリストを取得します | 誰でも可能 |
Amazon API Gatewayでのアクセス制御
Amazon API GatewayでAPIへのアクセス制御を行うにはAuthorizerの機能を使用します。公開してはならないAPIはしっかりと保護して強固なセキュリティを担保するようにしましょう。以下のような機能がAmazon API Gatewayでは提供されています。
- APIキー
本来、APIキーは WebAPI の認証に使用する用途のものではありませんが、APIキーを発行することでそのキーを知っているもの以外のAPIへのアクセスを制限することは可能です。また、APIキーごとに呼び出し回数に制限を設けることも出来ます。しかし、これはセキュリティ対策としては非常に簡易なものです。キーが漏れてしまえばそれだけで世界中からアクセスをされてしまいます。強固なセキュリティを担保するにはその他の方法を使用することを推奨します。
- JWTオーソライザー
OIDCやOAuth2.0で使用されるJWTトークンを使用した認可の仕組みです。Auth0やADFS、Amazon Cognito、Azure AD、Google など Open ID Connect をサポートするIDプロバイダーを使っている場合は簡単にアクセス制御が可能です。
- Lambdaオーソライザー
Lambdaで独自のプログラムを組んで認可の仕組みを実装します。
AWS Lambdaのアプリケーションコード内で実装すべきアクセス制御
アプリケーションロジックの中で、そのユーザに所属するデータ以外は操作してはならないというユースケースはよくあるでしょう。例えばECサイト内でカードに入れた商品や購入履歴などが他のユーザに見れてしまうというのはまずいでしょう。これらはAWSの機能では実装が出来ないのでアプリケーション内にバリデーションの仕組みを入れて実装するようにしましょう。どのレイヤーまでのセキュリティ対策をAWSの機能を使用して行うのか、それ以降はアプリケーションロジックとして実装するのか、またはサードパーティの製品などを入れて対策するのかはしっかりと整理して実装を行いましょう。