BeeX Tech blog

BeeXではクラウドネイティブアプリ開発、企業の基幹クラウド基盤構築、システム移行、運用保守を行っています。

Webhook URL を暗号化して AWS SAM で使うために頑張ったこと


今年もいろいろ頑張りました。来年もいろいろ頑張ります。那須です。

セキュリティの観点からアクセスキー等のバレたらまずい情報って誰にも見られない場所に保存するか、もしくは最低でも暗号化して保存しますよね?

かつ、アプリのデプロイや環境の構築は手作業でやりたくないので CloudFormation 等で対応している方も多いと思います。

どうすれば最低限のセキュリティを維持しながら作業を CLI 化、テンプレート化できるか、今回はその試行錯誤の過程を共有します。

AWS SAM を利用して Lambda 関数をデプロイするシナリオを例に書いていきますね。

最初は AWS SAM テンプレートに書いていた

Lambda 関数を環境変数と一緒にデプロイする AWS SAM テンプレートを作っていました。

環境変数の 1 つには、Slack の Webhook URL が含まれていて、この文字列を誰にもバレないようにしたいのが要件です。

最初は、「KmskeyArn を指定すればいけるやろ」って思って以下のようにテンプレート内に直書きしてました。

 Function:
  Type: AWS::Serverless::Function
  Properties:
    Environment:
      Variables:
        slack_url: https://slackurl/
    KmsKeyArn: KMS CMK の ARN

でデプロイしたらこんな感じになりました。

これでは AWS アカウントに入って Lambda 関数を見る権限がついていればバレてしまう…

「伝送中の暗号化のためのヘルパーの有効化」にチェック入れたいけど、調べてみると AWS::Serverless::Function では定義できないようです。

もしかしたら AWS::Lambda::Function でテンプレート定義すればできるかな?と思いましたが、やっぱり構文の中に定義できるものがありませんでした。

かといって、テンプレート内に暗号化したテキストをそのまま書くと、「あれ?元のテキスト何やったっけ?」ってなりがちですし、いちいち複合処理するのも面倒です。

これではいけない。

そこで次の策を考えました。

パラメータストアに入れるようにすればいいのでは?

SSM パラメータストアには SecureString というタイプのパラメータがあります。

暗号化されて KMS CMK を使えるユーザでないと復号化できないので安全ですね。

これを CloudFormation で書いて入れてしまえばいいのでは??

よし、早速 AWS::SSM::Parameter 構文を確認しよう!

docs.aws.amazon.com


AWS CloudFormation は SecureString パラメータタイプの作成をサポートしていません。

アカンやん…

そもそもよく考えたら、公開できない情報をテンプレートに書いたらそのテンプレート見られたらバレるし、GitHub 等でコード管理する際に一緒にアップロードするのでどのみちダメですね。

もう少し早く気づけばよかったです…

結局どうしたのか?

最初に SSM パラメータストアに手作業で Slack Webhook URL を保存することにしました。

これなら KMS CMK を利用できるユーザであればいつでも簡単に復号化できますし、その他の方や Lambda 関数からはプレーンテキストで読み取ることはできません。

また、他の Lambda 関数からも使えるので環境変数に書くよりは再利用性があっていいですね。 

AWS SAM テンプレートは、以下のように変更しました。

SSM パラメータのキーを基に、値を復号化して取ってくる処理をコードに追加しています(コードは省略)。

これでやりたかったことを実現できました。 

 Function:
  Type: AWS::Serverless::Function
  Properties:
    Environment:
      Variables:
      slack_url_ssm_parameter: SSM パラメータのキー
    KmsKeyArn: KMS CMK の ARN

まとめ

Lambda 環境変数に入れるとコンソールですべての関連情報が見れて便利ですが、環境変数の情報を再利用したりテンプレート等でプレーンテキストで書かずに管理したい場合に困る場面がありますよね。

そういう場合、機密情報を AWS SAM や CloudFormation のテンプレート内に書かずに SSM パラメータストアに入れて使うのがいくつかあるやり方の 1 つになります。

もしかしたらもっといいやり方があるかもしれませんが、環境やアプリをどう管理するかで決まってくる気がしますね。

(おまけ)Slack から Webhook URL を無効化された話

GitHub にアプリのコードや今回作成した AWS SAM テンプレートを push しました。

その数分後に、Slack からメールが来ました。

GitHub に Webhook URL が上がってるのを見つけたから削除しといたで、って内容です。

あとで何が悪かったのかを調べるために変更前のコードを同じディレクトリに.old等の名前をつけていたんですね。

で、.gitignore にそれを書くのを忘れて git push してしまったがために、Webhook URL が書かれた AWS SAM テンプレートを GitHub に公開してしまったという流れです。

今回は私の AWS SAM の練習のためのアプリだったので特に実害はないですが、アクセスキーやシークレットキーだけではなく、Webhook URL も知られるとバンバン post されかねないので公開しないように注意しましょう。