AWS KMS の encrypt API を使って、パスワード管理を行う

AWS KMSとは?

暗号化操作に使用されるキーを作成、管理することができるAWSのマネージドサービスです。

今回したいこと

DBのパスワードなど低容量のデータを暗号化したいのでカスタマーデータキー(CDK)を作成せず、KMSのencrypt APIを使ってカスタマーマスターキー(CMK)から暗号化を行います。

AWS CLI ドキュメント => https://awscli.amazonaws.com/v2/documentation/api/latest/reference/kms/index.html

事前準備

AWSコンソールからCustomer Managed Key(CMK)を作成し、キーID or aliasを取得

  1. KMSの画面へ移り、左ペインからカスタマー管理型のキーを選択
  2. キーの作成を押下
  3. 今回はデフォルトのまま画面に従って進みます、aliasは「sample/key」としておきます
  4. 管理、使用アクセス許可ではUserかRoleを指定して設定します
  5. 生成されたキーポリシーを確認して問題なければ完了、CMKが作成されキーID or alias を取得できるようになります

CloudShellを使いAWS CLIを操作する

CloudShellを使用することでアカウントのPermissionを持った状態ですぐにAWS CLIを叩くことができます

CloudShellのAWS CLIのバージョンは以下でした

$ aws --version
aws-cli/2.8.12 Python/3.9.11 Linux/4.14.294-220.533.amzn2.x86_64 exec-env/CloudShell exe/x86_64.amzn.2 prompt/off

以下の図のアイコンを押下してCloudShellを立ち上げます

まずは、暗号化、復号化の動作を確認していきます

暗号化したい文字列をplaintext.txtに保存します

$ echo 'password' >> plaintext.txt

encrypt APIで文字列の入ったファイルを指定し暗号化、CiphertextBlobの項目はbase64 encodeされた形式で出力されるのでこれをdecodeし、結果をencrypted.txtに保存

$ aws kms encrypt --key-id < CMK の KEY ID > or < "alias/" + CMK の alias名 > \
--plaintext fileb://plaintext.txt \
--output text \
--query CiphertextBlob | base64 --decode  > encrypted.txt

decrypt APIで復号化する場合は暗号化情報の入ったファイルだけを指定してPlaintextで取得、base64 encodeされているのでdecodeを行い、decoded-plain.txtに保存。中身を確認すると’password’が保存されています

ここで key-id を指定しないのは CiphertextBlob に key-id などのメタデータが含まれているからのようです

$ aws kms decrypt \
--ciphertext-blob fileb://encrypted.txt \
--output text \
--region ap-northeast-1 \
--query Plaintext | base64 --decode > decoded-plain.txt

運用例

以下はLambdaなどの環境変数に CiphertextBlob を保存し、DB接続に使用する例です

encrypt API コマンドの返り値の CiphertextBlob から base64 encode されている値を取得

$ aws kms encrypt --key-id < CMK の KEY ID > or < "alias/" + CMK の alias名 > \
--plaintext fileb://plaintext.txt \
--output json

>>
{
    "CiphertextBlob": "xxxxxxxx",
    "KeyId": "arn:aws:kms:ap-northeast-1:xxxxxxx:key/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
    "EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}

PythonのSDKで以下のように復号化し、passwordを取得、DBへ接続する

import base64
import boto3
import os
import psycopg2

kms_client = boto3.client('kms')

class EstablishPgsqlConnection:
    @staticmethod
    def decrypt_kms_key(ciphertext_blob: str) -> str:
        try:
            res = kms_client.decrypt(
                CiphertextBlob=bytes(base64.b64decode(ciphertext_blob))
            )['Plaintext'].decode('utf-8')
            return res
        except Exception as e:
            raise e

    @classmethod
    def establish_pgsql_connection(cls):
        connector = psycopg2.connect(
            'postgresql://{user}:{password}@{host}:{port}/{dbname}'.format(
                user=os.environ.get('DB_USER'),
                password=cls.decrypt_kms_key(os.environ.get('CiphertextBlob')),
                host=os.environ.get('DB_HOST'),
                port=os.environ.get('DB_PORT'),
                dbname='dbname'
            )
        )
        return connector

まとめ

今回はKMSを使いDBのpasswordを運用する手順を紹介しました

他にもSSMのPatameter Store の SercureString などを利用する運用などもありますが、手間や費用などを考えて最適な構成を選択していければよいと思います!

無料相談実施中
AWSを使用したサーバーレスアプリケーションの構築
サーバーレス開発内製化、AWSへの移行等
様々な課題について無料でご相談お受けいたします。
最新情報をチェックしよう!