SOPSで秘密情報ファイルを安全に管理する

記事タイトルとURLをコピーする

技術1課の水本です。

アプリケーション開発において、シークレット(秘密情報)の受け渡しは誰もが課題にするところではないでしょうか。

  • dotenvファイル(Nuxtなど)
  • database.yml(Rails)

DevOpsというワードが飛び交っている今でも、インフラ担当は「なるべくアプリチームの使い勝手を変えないまま、安全に管理する方法」を考えておられると思います。

今回はその方法のバリエーションのひとつとして、「SOPS」を用いた暗号化について紹介します。

SOPSとは?

SOPS(Secrets OPerationS)とはMozilla(Firefoxなどの開発元)が公開している暗号化ツールです。

github.com

暗号化ツールというのは他にも存在しますが、SOPSはPGP鍵での暗号化機能の他、以下の特長を持ちます。

  1. 主要クラウド(AWS、Google Cloud、Azure)の鍵サービスで発行した鍵を用いての暗号化に対応
  2. ファイルの種類を判別して値だけを暗号化済値に差し替えるので、暗号化済みファイルでも内容が読める(対応ファイル:YAML/JSON/Dotenv/INI)

何が便利なのか?

「AWSならSSMパラメーターストアみたいに、各種クラウドにもシークレットの専用管理サービスがあるのでは?」と思われるでしょう。

しかし、アプリ開発チームが必ずしもAWSの操作に長けているわけではなく、「なるべくAWSは触らずに楽に開発したい」との要望が出たときに考えられる手段は「シークレットはファイル化し、Gitのpushに連動して暗号化する」だと考えます。

例えば、以下の条件の環境があるとしましょう。

  • アプリのシークレットを.envファイルに格納している
  • .envにはDB認証情報が書かれており、GitHubへのアップは禁止

この場合、下記の通りに自動化することで、安全にシークレットの受け渡しが可能であり、アプリ開発チームは特にAWSを操作せず、安全にシークレットをインフラに受け渡すことが可能になります。

  1. 非公開なS3を作成する(シークレット管理用)
  2. アプリコードを格納したGitHubリポジトリに、.env.enc.envにリネームした形で暗号化してS3へアップロードするCIを設定
  3. 2をトリガーとして.enc.envとアプリコードを入手する後続ジョブをスタート
  4. .enc.env復号して.env
  5. 4をアプリコードにマージしてインフラにデプロイ

実際に暗号化してみる

では実際に暗号化をしてみます。

準備

下記が必要ですので事前に準備ください。

  1. SOPSをインストール済
  2. AWS CLIセットアップ済みで、正しくプロファイルの設定まで完了している
  3. 1から暗号化復号化できるKMS鍵が発行済み(ARNを控えてください)

暗号化

では、下記のファイル.envを暗号化してみましょう。 このファイルは適当に作ったものです。

DBHOSTNAME="mygreatdbhost"
DBUSERNAME="mydbmasteruser"
DBPASSWORD="mydbmasterpassword"

DB情報がそのまま入ってしまってます。危険ですね。
(本来はこんなことは無いと思いますが)

では、このファイルに対して暗号化を行ってみます。 方法はシンプルで、
sops -e --kms (KMSのARN) (--aws-profile AWS CLIのプロファイル名。省略可能) (ファイル名) > (暗号化後ファイル名)
です。

$ sops -e --kms  arn:aws:kms:ap-northeast-1:123412341234:alias/sops-demo --aws-profile swx-labo .env > .enc.env

暗号化ファイル.enc.envはこんな感じになります。

DBHOSTNAME=ENC[AES256_GCM,data:QBQJ3t3reViojLI7NMSZ,iv:x5NcyhKlWfj34g031ByWwi/eFKfjCs3WZMSmtfOGRrg=,tag:DZ+wuOaJm33xt7RUm5UQjA==,type:str]
DBUSERNAME=ENC[AES256_GCM,data:wpuYMykNW3c7AEBy1dvgnA==,iv:s3JJ99TShKOY1XdGvNuAy8b5DYSFsEppq9ayrCBhlbQ=,tag:Cr8+/IK67KO2ZLY5B66rFg==,type:str]
DBPASSWORD=ENC[AES256_GCM,data:EA7pw5sObLqNJIl/4t47j41SAEQ=,iv:uQEhScWwXgF8JipQ8iL759GYbo5bAoB4dZ+NKobHhNM=,tag:/A/XPCoJ6g4bHwy29LMxhg==,type:str]
sops_unencrypted_suffix=_unencrypted
sops_version=3.7.1
sops_mac=ENC[AES256_GCM,data:j3XkbxFu1nPtKbZCwiGPOC7VpZxBqM5+wafkP57+YLbhT8AksbgHntC2CQDhF9O+b3aAzUKJf1t4WNBXMM/YA7Koy77kKaHu+tex7JzG/DUNGTQXsUZrqQXUc3A2yAkj24hHAAM4B3tk4zC9Qah81Abymla9s2kYnpXuD0lPyOU=,iv:xqL466FIwlHDfHhapgmFmpyBjnTo9O/CJR7IBB4VFeI=,tag:GZZcB78ARVSFS1MlPHGgRg==,type:str]
sops_lastmodified=2021-10-21T06:52:49Z
sops_kms__list_0__map_arn=arn:aws:kms:ap-northeast-1:123412341234:alias/sops-demo
sops_kms__list_0__map_created_at=2021-10-21T06:52:49Z
sops_kms__list_0__map_enc=AQICAHhaAtv1/ZjvWfP/a+ng4YhCpQSY/iMr6eOwRzlD9G6QSAE0G9HESBSt8x/bK1zG4ClHAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM1D+VhC8Lau1mKFV4AgEQgDu19BtTezYjIUYY9oCzp9buFaiz8XNMtoe/zRxkllxewBwDw/C9MQoYIAQyg/FU+J126iSFTJSVHHSMTw==
sops_kms__list_0__map_aws_profile=swx-labo

暗号化前と比べて変化がありますね。

  • キー名はそのままに、値が暗号化されている
  • sops_で始まるキーが追加されている
    • 暗号化管理・復号化に使うメタデータ
DBHOSTNAME=ENC[AES256_GCM,data:QBQJ3t3reViojLI7NMSZ,iv:x5NcyhKlWfj34g031ByWwi/eFKfjCs3WZMSmtfOGRrg=,tag:DZ+wuOaJm33xt7RUm5UQjA==,type:str]
DBUSERNAME=ENC[AES256_GCM,data:wpuYMykNW3c7AEBy1dvgnA==,iv:s3JJ99TShKOY1XdGvNuAy8b5DYSFsEppq9ayrCBhlbQ=,tag:Cr8+/IK67KO2ZLY5B66rFg==,type:str]
DBPASSWORD=ENC[AES256_GCM,data:EA7pw5sObLqNJIl/4t47j41SAEQ=,iv:uQEhScWwXgF8JipQ8iL759GYbo5bAoB4dZ+NKobHhNM=,tag:/A/XPCoJ6g4bHwy29LMxhg==,type:str]

しっかりDB接続情報は分からなくなっていますね。

復号

復号の際は鍵情報をメタデータから取得するので、特に指示は不要です。 sops -d .enc.env > .env

なお、暗号化ファイルを直接編集することも可能です。 $EDITORのエディタが開かれます。

sops .enc.env

注意事項

  • 最初の例に挙げておいてなんなのですが、試しにRailsから作ったdatabase.ymlを暗号化して復号したところ、どうやら<<: *defaultの表記を正しく解釈できないようなので、この表記をやめる、環境変数を取り込むenvファイルを暗号化管理し、ENVから読む、バイナリファイルとして全体を暗号化するようオプションで指示する、のいずれかにしたほうが良さそうです。

以上、SOPSを用いた秘密情報ファイル管理方法の紹介でした。

水本 正敏(執筆記事の一覧)

クラウドインテグレーション部 技術1課

国内ITベンダーのカスタマーエンジニアからAWSに魅了されサーバーワークスへ。