概要
外部APIのAPIキーを保持する、マルチテナント型SaaSを開発されている方も多数いらっしゃるかと思います。
バックエンドとしてAPIキーをどのように保持すべきか?考えてみました。
設計方針
設計方針としては、以下になるかと思います。
- シークレットは「読み取り専用」に絞る
- APIキーは書き換えや参照が頻繁に行われるものではありません。アプリケーションから必要に応じて「読む」だけでよいので、データベースやファイルに平文で置かず、読み取り専用の仕組みを用意します。
- 平文配置した瞬間に、鍵は暴かれるリスクが高まります。どれほどセキュアなサーバーでも、不慮のミスや権限の漏れはゼロにはできません。だからこそ、「読むためには真正性を示し、限定的にしか触れられない場所に格納する」ことが大前提です。
- テナントごとに「分離」を徹底する
- マルチテナント環境では、A社のAPIキーをB社から参照されてはいけません。
- テナントIDをベースに「名前空間」を分ける、あるいはテナントごとに別のシークレットストアを使うなど、キーの保存先を論理的・物理的に分離しましょう。
- 暗号化キー(KMS)は別管理
- シークレットそのものを暗号化して保存する場合、暗号化/復号の鍵(KMSキー)はアプリケーションサーバーとは別の場所で管理します。
- クラウド利用なら「AWS KMS」「Azure Key Vault」「GCP Cloud KMS」といったマネージドKMSを活用し、何があっても平文の鍵が流出しない構造を作ります。
- アクセス権限は「最小権限」に絞る
- アプリケーション本体(バックエンド)がシークレットを取りに行く際は、「読む権限」しか与えないIAMロール/サービスプリンシパルを用意します。
- 本番とは別の環境(ステージング・開発)を用意するなら、それぞれに異なるキーを発行し、本番のキーには一切触れられないようにします。
- 監査ログを有効化する
- 誰がいつ、どのテナントのどのシークレットにアクセスしたのかを必ずログに残す。
- もし不正にアクセスを試みる攻撃者がいても、ログをたどることで侵入経路や責任所在を明確にできます。
- 可能であれば、定期ローテーションを組み込む
- 「一度発行したAPIキーはずっと使い続ける」運用は危険です。
- 毎月または四半期に一度、(あるいはテナントの要望に応じて)自動的に新鍵に切り替える仕組みを用意しましょう。
- ローテーションといっても面倒ではありません。秘密情報の扱いを自動化し、心にゆとりを持った運用を実現しましょう。
2. 具体的な実装パターン例
ここでは代表的な3つのアプローチを示します。どれもメリット・デメリットがありますので、自社の運用規模やクラウドサービスの採用状況に合わせて選択してください。
2.1. クラウドシークレットマネージャ(AWS Secrets Managerなど)の活用
構成イメージ
┌───────────────────┐
│ クラウドKMS/KV │ ← APIキーを暗号化して保管。例: AWS Secrets Manager 、
│(AWS Secrets │ Azure Key Vault、GCP Secret Manager 等
│ Manager など) │
└───────────────────┘
↑
│(暗号化/復号リクエスト)
│
┌───────────────────┐
│ バックエンド │ ← シークレットを読む専用のIAMロールを付与
│ (APIサーバー等) │
│ │
└───────────────────┘
- テナントごとにシークレットを作成する
- 例えば AWS Secrets Manager なら、シークレット名を
/saas/myapp/tenant-{tenant_id}/external-api-keyのように命名します。 - Azure Key Vault も同様に「VaultName/tenant-{tenant_id}-api-key」という形で分ければよいでしょう。
- 例えば AWS Secrets Manager なら、シークレット名を
- 読み取りはSDK経由で行う
- バックエンドからはAWS SDK(Java/Python/Node.js など)や Azure SDK を通して「SecretId(名前)」を指定して暗号化済みのAPIキーを取り出す。
- SDK呼び出しの際、実行環境のInstance Profile や Service Principal に「読み取り権限」だけを与えることで、不正な書き換えや作成を防ぎます。
- ローテーション機能を自動化
- AWS Secrets Manager には「自動ローテーション機能」があり、Lambda関数を組み合わせれば数分で新鍵発行→置き換え→デプロイ完了までを自動化可能です。
- ローテーションの度にテナントオーナーにアラートを送りたい場合は、SNS やメール連携を活用するとよいでしょう。
- メリット
- マネージドサービスなのでオンプレでVaultを立てる手間が不要
- KMSキーやアクセス権周りをクラウドベンダーが管理してくれる安心感
- 監査ログやローテーション機能がデフォルトで使える
- デメリット・懸念点
- クラウドベンダーのサービスロックインを招きやすい
- コストがテナント数×シークレット数でかさむ可能性がある
- クラウド側の障害が直撃すると、一時的にAPIキー取得自体ができなくなるリスクがある
実装ポイント(AWS例)
1. IAMロール作成
- 名前: MyApp-SecretReaderRole
- ポリシー例 (JSON抜粋):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": [
"arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:/saas/myapp/tenant-*/external-api-key-*"
]
}
]
}
2. シークレット作成
AWS CLI:
$ aws secretsmanager create-secret \
--name "/saas/myapp/tenant-1001/external-api-key" \
--description "テナントID=1001向けの外部APIキー" \
--secret-string '{"api_key":"YOUR_API_KEY_HERE\
