serverless frameworkでpublic repositoryに含めるべきではないデプロイ情報を扱う

AWS Lambdaの開発環境としてServerless Frameworkを使ってみることにしました。

Frameworkと銘打っていますがソフトウェアの中に組み込んで使うフレームワークではなく、各種のSource Code as a Serviceに対するデプロイや運用をサポートしてくれるためのツール*1になります。

で、チュートリアルにならって serverless.yml の設定を書いていたのですが、以下の疑問が沸いてきました。

  • provider.deploymentBucket.name でデプロイ先バケットを指定できるが、publicリポジトリに登録する場合にうれしくないのでは?*2
  • 同様に各種ソースコードで利用する極秘情報(API Keyなど)をどのように保持するのか。

で、調べてみた結果、Systems Manager Parameter Store を利用するか、依存関係を別ファイルに切り出すかで解決できます。

Systems Manager Parameter Store を利用する

Parametere Store へのアクセスができないとかでない限りは基本的にこちらを推奨します。

https://dev.classmethod.jp/cloud/aws/parameter-store-application-config/

アプリケーションで利用する環境変数を EC2 Systems Manager で利用可能にする機能ですが、これを serverless framework のデプロイおよび実行の際にも利用することが可能です。

まず、デプロイ実行時に利用する変数をawscliでデプロイします。

# 必要に応じて --profile を指定する
aws ssm put-parameter --name sls.deploymentBucket --type String --value your-bucket-name

その後 serverless.yml 内で ${ssm:} と記述することでそこに登録している値を利用できます。

# serverless.yml から抜粋
provider:
  deploymentBucket:
    name: ${ssm:sls.deploymentBucket}

API Tokenなどの秘匿情報を保持させる場合、aws ssm put-parameter --type SecureString を利用して暗号化した情報をParameter Storeに保存します。

しかし、SecureStringで暗号化されたパラメータを serverless.yml 内で指定した場合は暗号化されたままの内容が serverless.yml 上に展開されます。
SecureStringで指定した内容はデプロイ時には利用せず、Lambdaの内部で Systems Manager の GetParameters を利用して複合してください。

例えばPythonの場合は boto3.client('ssm').get_parameter(Name=key, WithDecryption=True) などで獲得できます。

より細かくは公式のチュートリアルを参照ください。

https://serverless.com/blog/serverless-secrets-api-keys/

依存関係を別ファイルに切り出す

基本的には Parameter Store を利用することを推奨しますが、例えばAWSアカウントのSSMアクセス権限がない場合などに利用できます。

serverless.yml の中で別のファイルを読み込み、その変数を使うことができます。
その時には ${file(ファイル名):内部変数名} を利用できます。

# serverless.yml から抜粋
provider:
  deploymentBucket:
    name: ${file(./secrets.yml):SLS_DEPLOY_BUCKET}
# secrets.yml の一例
SLS_DEPLOY_BUCKET: your-bucket-name

Systems Manager Parameter Store について

というかサービスの詳細を見落としてましたが、コレものっっすごく便利ですね。

割とAWSデプロイ時の変数をうまいこと格納できる方法がリポジトリに同梱するとかS3にアップロードしておくとかの方法しか思いつかなかったので、ここの値をうまく使うのはいい感じにデプロイ時の値の保持を解消してくれるソリューションとして利用できて非常にうれしいです。

なお、通常の ssm get-parameter / put-parameter を利用する場合は AWS が SSM を利用するときにデフォルトで生成する alias/aws/ssm という KMS 管理下の鍵を内部で利用して自動的に暗号化・複合化してくれているようなので、自前で暗号化・複合化に利用する鍵のことを考えなくて済むのも非常にポイントが高いです。

*1:最初は名前だけ聞いてどうやって各種のプロジェクトに組み込むものかと思っていた

*2:バケット名は全AWSアカウントでユニークである必要があり、自分以外の人がチェックアウト・デプロイするタイミングでそのまま使おうとすると該当AWSアカウントのクレデンシャルを持っていない限り絶対に失敗する