Amazon Connect暗号化した入力値をPythonで復号して利用する

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

概要

Amazon Connectの問い合わせフローでは、AWS Lamdaと組み合わせることで顧客の入力した番号による処理を実装することができます
たとえば、クレジットカード番号や、取引暗証番号の入力に利用するケースが考えられます

Amazon Connectでは顧客入力情報を暗号化した状態で保持する機能が準備されています
情報を利用する際には復号する必要がありますが、これをPythonで実装する方法を紹介します

手順

AWS様のブログ手順にならった流れとします
(ブログではNode.jsで作成されたServerlessアプリケーションをデプロイしていますが、本手順ではPythonコード+Layerを手動デプロイします)

Amazon Connectで作るセキュアなIVRソリューション | Amazon Web Services ブログ

  1. 秘密鍵、証明書、公開鍵を作成する
  2. 秘密鍵を AWS Systems Managerパラメータストアへ保存する
  3. 復号処理をLambdaへセットアップする
  4. 公開鍵を Amazon Connectへアップロードする
  5. Lambda関数の使用許可設定を行う
  6. 暗証番号を入力、保持する問い合わせフローを作成する
  7. 動作確認

使用した環境等

  • Ubuntu 20.04 on WSL2
  • Python 3.8.6
  • aws-cli/2.0.50

1. 秘密鍵、証明書、公開鍵を作成する

秘密鍵(test.connect.private.key)、証明書(test.connect.certificate.pem)を作成します
動作確認のため、Country Nameなどは適当に入力します

openssl req -x509 -sha256 -nodes -newkey rsa:4096 -keyout test.connect.private.key -days 365 -out test.connect.certificate.pem

証明書から公開鍵(test.connect.public.key)を出力します

openssl x509 -pubkey -noout -in test.connect.certificate.pem > test.connect.public.key

2. 秘密鍵を AWS Systems Managerパラメータストアへ保存する

aws ssm put-parameter --type SecureString --name TEST_CONNECT_KEY --value "$(<test.connect.private.key)"

コンソールから確認できます

f:id:swx-shinsaka:20201019181010p:plain

3. 復号処理をLambdaへセットアップする

3-a. 必要なモジュールを含んだLayerを作成します

今回は amazon-connect-decryption-lib というモジュールを使用します
aws-encryption-sdk 等の必要なモジュールへも依存しているので下記でレイヤー用のzipファイルを作成します

pip install amazon-connect-decryption-lib -t layers/python
cd layers
zip -r decryptionLayer.zip python/

3-b. レイヤーをアップロードして登録します

aws lambda publish-layer-version --layer-name decryptLayer --zip-file fileb://./decryptionLayer.zip --compatible-runtimes python3.8

3-c. Lambda関数を作成します

コンソールから作成します
関数名: connectDecryptPython

f:id:swx-shinsaka:20201019183154p:plain

前の手順でアップロードしたレイヤーを指定します

f:id:swx-shinsaka:20201019183939p:plain

3-d. lambda_function.pyの内容を下記に変更します

問い合わせフロー属性 SecretNumber の内容を復号してログに出力する処理としました

from amazon_connect_decryption_lib import decrypt

def lambda_handler(event, context):
    ssm_parameter_name = 'TEST_CONNECT_KEY'
    encrypted_text = event['Details']['ContactData']['Attributes']['SecretNumber']
    
    plain_text = decrypt(ssm_parameter_name, encrypted_text)
    print(plain_text)

    return {'DecryptResult': plain_text }

3-e. Lambda実行ロールを修正します

  • 下記のようなポリシーを設定し、Systems Managerパラメータへのアクセスを許可します
  • ここでは検証のため、Resource=* としています
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ssm:DescribeParameters",
                "ssm:GetParameterHistory",
                "ssm:GetParametersByPath",
                "ssm:GetParameters",
                "ssm:GetParameter"
            ],
            "Resource": "*"
        }
    ]
}

4. 公開鍵を Amazon Connectへアップロードする

コンソールからAmazon Connectの該当インスタンスページへアクセスします
問い合わせフロー→問い合わせフローのセキュリティキー→キーの追加を操作します

f:id:swx-shinsaka:20201019185059p:plain

手順1で作成した 公開鍵(test.connect.public.key)の内容をコピーペーストします

f:id:swx-shinsaka:20201019185349p:plain

追加後、キーIDを控えておきます

f:id:swx-shinsaka:20201019185549p:plain

5. Lambda関数の使用許可設定を行う

Amazon Connectの該当インスタンスページ→問い合わせフロー→AWS Lambdaから、手順2で作成したLambda関数の利用を許可します

f:id:swx-shinsaka:20201019190139p:plain

6. 暗証番号を入力、保持する問い合わせフローを作成する

問い合わせフローの該当部分

  1. 顧客へ暗証番号の入力を促し、保存(暗号化)
  2. 暗号化された暗証番号を問い合わせ属性 SecretNumber へ保持
  3. 復号処理を実装したLambdaを呼び出す
  4. Lambda関数の処理結果によって音声を再生し、終了

f:id:swx-shinsaka:20201019190944p:plain

6-a. 顧客へ暗証番号の入力を促し、保存(暗号化)

「顧客の入力を保存する」ブロックを配置し、下記設定します

  • [エントリを暗号化する] をチェック
  • [キーの入力]を選択
  • [キーID] へ、手順4設定した、「問い合わせフローのセキュリティキー」で控えたキーIDを指定
  • [キー] へ、手順1で作成した 証明書(test.connect.certificate.pem)の内容をコピーペーストします

f:id:swx-shinsaka:20201020105436p:plain

6-b. 暗号化された暗証番号を問い合わせ属性 SecretNumber へ保持

「問い合わせ属性の設定」ブロックを配置し、下記設定します

  • [属性を使用する]を選択
  • [宛先キー]へ "SecretNumber" を指定
  • [タイプ]="システム"を選択
  • [属性]="保存済みのお客様の入力"を選択

f:id:swx-shinsaka:20201020092850p:plain

6-c. 復号処理を実装したLambdaを呼び出す

「AWS Lambda関数を呼び出す」ブロックを配置し、下記設定します

  • [関数を選択する]="connectDecryptPython"を選択 (手順2で作成したLambda関数)
  • タイムアウトを適切に設定

f:id:swx-shinsaka:20201020093415p:plain

6-d. Lambda関数の処理結果によって音声を再生し、終了

今回は動作確認のため、Lambdaブロックの成功・失敗それぞれ分岐先へ「プロンプトの再生」ブロックを設置しました

f:id:swx-shinsaka:20201020093919p:plain

f:id:swx-shinsaka:20201020093936p:plain

7. 動作確認

実際に電話を掛け、問い合わせフローを動作させ、暗証番号入力してみます
"0355798029" を入力してみました(サーバーワークスの代表電話番号です)

  • CloudWatch Logsで問い合わせフローログを確認すると、入力値が暗号化されていることが確認できます
  • 下記画像上段が「顧客の入力を保存する」ブロック、下段が「問い合わせ属性の設定」ブロックのログです
  • Base64エンコードされた暗号化データが "SecretNumber" 属性キー値としてセットされています

f:id:swx-shinsaka:20201020103136p:plain

  • 復号Lambdaの結果は平文になっていることが確認できます

f:id:swx-shinsaka:20201020101852p:plain

  • 問い合わせ追跡レコード(CTR)を確認しても、属性値が暗号化されていることが確認できます

f:id:swx-shinsaka:20201020103744p:plain

まとめ

今回はLambda関数を手動デプロイしたので手順が煩雑になってしましましたが、ServerlessFrameworkなどを使うことでスマートにするのが良さそうです
顧客からの入力を暗号化することで、機密情報をセキュアに取り扱うことができることを確認できました