Secrets Managerで機密情報を守る!Serverless Frameworkでの実践例

※当サイトは、アフィリエイト広告を利用しています。

くれとむ

AWS Secrets Managerってどんな役割を担っているか知ってる?

チーズくん

うん!アプリケーションで使うAPIキーやデータベースの認証情報みたいな機密情報を安全に管理して、必要なときだけ取り出せるようにしてくれるんだよね!
『秘密を守る金庫』みたいでワクワクするよね!

くれとむ

うんうん。その金庫を安全に使うには、正しい設定と運用が必要なんだよ。
今回はその使い方について解説するよ!

この記事では、AWS Secrets Managerを使ってServerless Framework(※)のserverless.ymlから機密情報を安全に取得する方法を解説します。
Secrets Managerでのシークレット作成から、動作確認まで、初心者でも分かりやすいステップでご紹介します。

AWSの「秘密を守る金庫」を正しく使いこなすための第一歩を踏み出しましょう。

※Serverless Frameworkとは?

Serverless Frameworkは、サーバーレスアプリケーションを簡単に構築・管理できるオープンソースフレームワークです。AWS LambdaやAPI GatewayなどのAWSサービスを効率的にデプロイできるツールで、特に複雑なサーバーレス構成のデプロイや管理に優れています。

Serveless Frameworkについて詳しく知りたい方は、以下の記事をご覧ください。

本記事で使用するコードのgithub

本ブログで用いているプロジェクトはGitHubリポジトリで公開しています。
以下のリンクからダウンロードしてください。
https://github.com/my-repo-441/SecretsManager-Demo

AWS Secrets Managerとは?

AWS Secrets Managerは、セキュリティを大幅に向上させるための非常に役立つサービスです。
このサービスを利用することで、データベースの認証情報やAPIキーなどの機密情報を安全に管理し、アプリケーションからAPIを介して簡単に取得できます。

Secrets Managerを使うメリット

1. 機密情報の一元管理:

  • Secrets Manager を使用することで、すべての機密情報を AWS 管理の一元化された環境で安全に保存できます。

2. IAM による厳格なアクセス制御:

  • Secrets Manager は IAM ポリシーを利用してアクセス制御が可能。特定のサービスやユーザーだけがアクセスできるように設定できます。

3. 動的なシークレットの更新:

  • シークレットを更新すると、それを利用するアプリケーションに即座に適用されます。再デプロイの必要がありません。

4. ログと監査の提供:

  • Secrets Manager は CloudTrail を通じてすべての操作(取得、更新、削除)を記録。セキュリティインシデントの監視が容易です。

5. 直接記載からの解放で安全性向上:

  • serverless.yml に機密情報を記載しないことで、バージョン管理や公開時の事故を未然に防げます。

機密情報管理の重要性

現代のアプリケーション開発では、APIキーやデータベースの認証情報など、多くの機密情報を管理する必要があります。
例えば、Serverless Framework を使用する際には、APIキーなどの環境変数を設定ファイル(serverless.yml)に直接記載するのはセキュリティリスクを高める原因になります。

具体的には、以下のようなリスクが考えられます。

機密情報管理に関するセキュリティリスク
  • バージョン管理システムへの漏洩
    • serverless.yml に機密情報を記載していると、Git などのバージョン管理システムにその情報が含まれ、誤って公開されるリスクが高まります。
  • チームでの共有時の課題
    • ファイルを通じて機密情報を共有する場合、意図しないアクセスや操作が発生する可能性があります。
  • セキュリティ標準への準拠不足
    • 多くのセキュリティ基準(例: ISO27001、SOC2)では、機密情報の安全な管理が求められます。

AWS Secrets Manager を使うことで、機密情報を安全に管理しながら開発効率を維持することが可能になります。

Secrets Managerの検証手順

本ブログでは、以下の手順でSecrets Managerの動作検証を行います。

動作検証手順
  1. Secrets Managerでシークレット作成
    • Secrets Managerのコンソール画面から、API キーのシークレットを作成します。
  2. AWS CLIからシークレット取得
    • AWS CLIを使って、シークレットが作成できているかをどうか確認します。
  1. Serverless Framework の設定
    • serverless.yml に IAM ポリシーを追加し、Lambda 関数からSecrets Managerにアクセスできるよう設定します。
  2. Lambda 関数での取得ロジック
    • AWS SDKであるboto3を使用して、Secrets Managerからシークレットを取得する実装を紹介します。

上記の手順で構築できる検証環境の構成図は以下です。
API GatewayからLambdaに対してGETメソッドでリクエストを送り、Secrets Managerから機密情報を取得するという流れです。

Secrets Managerでシークレット作成

Secrets Managerでシークレットを作成する手順は以下です。

手順
  1. AWS コンソールの Systems Managerを開く
  2. 新しいシークレットを保存するを押下
  3. シークレットタイプを選択する
  4. 新しいパラメータを作成し、それぞれの値を登録
    (例:OPENAI_API_KEYのAPIキー値)
  5. シークレットの名前を入力する。
    (例:OPENAI_API_KEY
  6. その他の値は基本的にはデフォルトで問題ない。
    シークレットを保存し、作成されていることを確認する。
Screenshot
くれとむ

今回は例として、キーを「OPENAI_API_KEY」、値を「OPENAIのAPIキー」としてシークレットを作成しました。

AWS CLIからシークレット取得

まずSecretsManagerで作成したシークレットが正常に作成完了しているかどうかを、AWS CLIから確認します。
aws secretsmanager get-secret-value コマンドで確認することができます。

aws secretsmanager get-secret-value --secret-id <SECRET_NAME> --region <REGION>
引数の説明
  • <SECRET_NAME>: Secrets Manager に登録した秘密情報の名前。
  • <REGION>: 秘密情報が保存されている AWS リージョン。
実行例
aws secretsmanager get-secret-value --secret-id my-secret-key --region ap-northeast-1

コマンド実行した結果、以下のように自身で作成したシークレットの情報が取得できれば成功です。

出力例
{
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:my-secret-key",
    "Name": "my-secret-key",
    "VersionId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
    "SecretString": "{\"OPENAI_API_KEY\":\"sk-example-key\",
    "VersionStages": ["AWSCURRENT"],
    "CreatedDate": 1672457600.0
}

このコマンドの出力には、シークレットの詳細情報が含まれており、特にデータベースに接続するために必要なユーザー名やパスワードが含まれます。

Serverless Frameworkの設定

次に、ServerlessFrameworkのserverless.yamlという設定ファイルに、Secrets Managerのシークレットを呼び出す設定を記載します。
動作確認のための簡易的なLambda関数も作成します。

ServerlessFrameworkを初回利用する場合

ServerlessFrameworkを初回利用する場合は、ツールのインストールおよび、サービスへの登録が必要です。
具体的な手順については、以下の記事をご覧ください。

まず、自身のローカル環境に、以下のようなフォルダ構成を作成します。

.
├── handler.py
└── serverless.yaml

serverless.yml

Serverless Framework の設定ファイルで Secrets Manager を参照する IAM 権限と環境変数設定を記述します。YOUR-SECRETS-KEYには自身のシークレットのARNから確認した値を記載します。

service: secrets-manager-demo

provider:
  name: aws
  runtime: python3.9
  region: ap-northeast-1
  environment:
    SECRET_NAME: my-secret-key  # Secrets Managerに登録したシークレット名
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - secretsmanager:GetSecretValue
          Resource: arn:aws:secretsmanager:${self:provider.region}:${aws:accountId}:secret:YOUR-SECRETS-KEY

functions:
  getSecret:
    handler: handler.get_secret
    events:
      - httpApi:
          path: /get-secret
          method: get

my-secret-keyの部分は、Secrets Managerのコンソール画面内で、作成したシークレットのARNから確認した値を記載します。

handler.py

このコードは、AWS Secrets Manager を使った機密情報管理の基本的なLambda 関数の実装例です。AWS SDK を使用して Secrets Manager から秘密情報を取得します。

import boto3
import os
import json

def get_secret(event, context):
    secret_name = os.environ['SECRET_NAME']
    region_name = os.environ.get('AWS_REGION', 'ap-northeast-1')

    # Secrets Manager クライアントの作成
    client = boto3.client('secretsmanager', region_name=region_name)

    try:
        # Secrets Manager からシークレットを取得
        response = client.get_secret_value(SecretId=secret_name)
        
        # シークレットが JSON 形式の場合の処理
        if 'SecretString' in response:
            secret = json.loads(response['SecretString'])
        else:
            secret = response['SecretBinary']

        return {
            "statusCode": 200,
            "body": json.dumps({
                "message": "Secret retrieved successfully.",
                "secret": secret
            })
        }

    except Exception as e:
        return {
            "statusCode": 500,
            "body": json.dumps({
                "message": "Error retrieving secret.",
                "error": str(e)
            })
        }

シークレットの取得

ServerlessFrameworkのdeployコマンドを使って、関数をデプロイします。

serverless deploy

もしくは

sls deploy

以下のようにGETメソッドのエンドポイントが出力されるので、そのURLにアクセスします。

SecretsManagerで作成した機密情報が表示されれば成功です。

WebアプリでのSecrets Managerの活用

上記の検証では、実際にSecrets Managerから機密情報を取得することを確認しました。

実際のWebアプリの画面もあった方が、よりSecretsManagerの使い方がわかりやすいと思いました。 実際にReactベースのフロントエンドのアプリ画面のコードも作成して、OpenAIのAPIキーを使った簡易的な検証アプリの動作を確認します。

システム構成図は以下です。

Githubからプロジェクトをクローン

以下のコマンドでGithubからプロジェクトをクローンします。
次に、openai-secrets-demoディレクトリに移動します。

git clone https://github.com/my-repo-441/SecretsManager-Demo.git
cd openai-secrets-demo

依存関係のインストール

backendディレクトリに移動して、以下のコマンドをライブラリをインストールします。

cd backend
npm install

同様に、frontendディレクトリに移動して、ライブラリをインストールします。

cd frontend
npm install

serverless.yamlの修正

SECRET_NAMEは、自身でSecrets Managerに登録したシークレットの名称およびARNに合わせて修正します。
YOUR-SECRETS-KEYには自身のシークレットのARNから確認した値を記載します。

service: openai-secrets-demo

provider:
  name: aws
  runtime: python3.12
  region: ap-northeast-1
  layers:
    - {Ref: PythonRequirementsLambdaLayer}  # レイヤーを追加   
  httpApi:
    cors:
      allowedOrigins:
        - http://localhost:3000
      allowedMethods:
        - POST
      allowedHeaders:
        - Content-Type

  environment:
    SECRET_NAME: OPENAI_API_KEY  # Secrets Managerに登録したシークレット名
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - secretsmanager:GetSecretValue
          Resource: arn:aws:secretsmanager:${self:provider.region}:${aws:accountId}:secret:YOUR-SECRETS-KEY

functions:
  invokeOpenAI:
    handler: handlers/invoke_openai.lambda_handler
    events:
      - httpApi:
          path: /invoke-openai
          method: post
    timeout: 29
plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    dockerizePip: true  # Dockerを利用して依存関係を正確にパッケージング
    layer: true
    slim: true          # 依存関係をスリム化

package:
  exclude:
    - node_modules/**
    - README.md
    - package-lock.json
    - .git/**
    - package.json
    - requirements.txt
    - requirements.zip
    - unzip_requirements.py    

フロントエンドでWebアプリを起動

frontendディレクトリに移動して、Webアプリを起動します。

cd frontend
npm start

localhost:3000Webアプリが起動します。

バックエンドのLambda関数をデプロイ

以下のコマンドでbackendし、Serverless Frameworkを使ってLambda関数をデプロイします。なお、serverless.yamlAPIでIAMロールやAPI Gatewayの設定も記載しているため、必要な設定も自動的に設定されるようになっています。

cd backend
serverless deploy

Webアプリの動作確認

Webアプリの動作確認を行います。
フロントエンドで起動したWebアプリの入力フォームに、何でも良いので質問を投げてみます。

すると、OpenAIのAPIにより処理された結果が出力されます。

くれとむ

バックエンドでは、Secrets ManagerからOpenAIのAPIキーを呼び出し、OpenAIのAPIによる処理が行われます。
具体的には以下のようなコードでOpenAIの処理を定義しています。

        system_message = (
            "プロンプトの内容を元に返信してください。"
        )
        user_content = f"プロンプト: {prompt}"

        messages = [
            {"role": "system", "content": system_message},
            {"role": "user", "content": user_content},
        ]

        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=messages,
            max_tokens=150
        )

まとめ

本記事では、AWS Secrets Manager を使用して Serverless Framework での機密情報管理を安全かつ効率的に行う方法を解説しました。
AWS Secrets Manager を使用することで、Serverless Framework での機密情報管理が安全かつ効率的に行えるようになります。

Secrets Managerを使った
  • Secrets Manager を導入するメリット
    • 設定ファイルに直接機密情報を記載するリスクを回避できる。
    • IAM による厳格なアクセス制御で、特定のサービスやユーザーだけがシークレットにアクセス可能。
    • シークレットの更新が即時適用され、運用中のアプリケーションを停止する必要がない。
  • 実践のポイント
    • Secrets Manager に API キーや認証情報を登録し、一元管理を実現。
    • Serverless Framework の serverless.yml で IAM 権限を適切に設定。
    • Lambda 関数から Secrets Manager のシークレットを動的に取得し、安全な運用を行う。
  • 安全な運用のために
    • IAM ポリシーの最小権限化を徹底して、不要なアクセスを防ぐ。
    • シークレット管理の簡素化を意識して、運用の手間を減らす。
    • コストを考慮しつつ、必要に応じて Secrets Manager の利用を拡張。

機密情報を設定ファイルに直接記載するリスクを排除し、セキュリティ事故を未然に防ぎましょう。
今回紹介した手法はServerless Frameworkの設定ファイル内にSecrets Managerで作成したシークレットを呼び出すという一例ですが、セキュアなアプリケーションを構築するために、本記事の内容が少しでも参考になれば幸いです。

最後まで読んでいただきありがとうございました。










コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


ABOUT US
くれとむ
IT企業で働いているシステムエンジニアです。 AWSなどIT技術のトレンドを発信します。 また、日常の課題を解決するライフハック記事や実体験をもとにしたレビューも発信します。 エンジニアならではの視点で、技術の楽しさと日常の快適さを繋げます! AWS認定(CLF, SAA, DVA, SOA, SAP, DOP, ANS, SCS, MLS)、基本情報技術者、応用情報技術者、情報処理安全確保支援士、TOEIC L&R 870点 ※このサイトはアフィリエイト広告(Amazonアソシエイト含む)を掲載しています。