はじめに
Lambda(VPC内)からオンプレのAPI(HTTPS、自己署名証明書)を叩くために、証明書をLambdaに信頼させた時のメモ。
やること
- pfxから証明書部分をPEMで取り出す
- Lambda Layerに載せる
- 環境変数でパスを指定する
1. pfx→PEM変換(PowerShell)
$pfxPath = "C:\work\server_certificate.pfx"
$password = Read-Host "pfxのパスワード" -AsSecureString
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($pfxPath, $password)
$der = $cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)
$base64 = [System.Convert]::ToBase64String($der, [System.Base64FormattingOptions]::InsertLineBreaks)
$pem = "-----BEGIN CERTIFICATE-----`r`n" + $base64 + "`r`n-----END CERTIFICATE-----`r`n"
Set-Content -Path "C:\work\onprem-ca.pem" -Value $pem -Encoding ascii
Write-Host "Subject: $($cert.Subject)"
Write-Host "Issuer: $($cert.Issuer)"
Write-Host "有効期限: $($cert.NotAfter)"
※
-
InsertLineBreaksを付けないとbase64が1行になり、パーサーによっては読めない -
-Encoding ascii必須。PowerShell 5.1のSet-ContentはデフォルトUTF-16(BOM付き)で、そのままだとLambda側で読み込みに失敗する
TLSクライアント側に必要なのは証明書(公開部分)だけなので秘密鍵は取り出さない。そもそも秘密鍵入りのpfxを受け渡しするべきではないので、依頼時点で.cer/.pem指定にしたほうがいいが、pfxでいただいたので上記で対応しました。
2. Lambda Layerに載せる
mkdir certs
copy onprem-ca.pem certs\
Compress-Archive -Path certs -DestinationPath certs-layer.zip
Lambdaコンソールの「レイヤー」→「レイヤーの作成」でアップロードして関数にアタッチ。
Layerの中身は /opt/ 以下に展開されるので、パスは /opt/certs/onprem-ca.pem になる。
「互換性のあるアーキテクチャ/ランタイム」は今回特に指定はない。
3. 環境変数でパスを指定
| ランタイム | 環境変数 | 値 |
|---|---|---|
| Python(requests) | REQUESTS_CA_BUNDLE |
/opt/certs/onprem-ca.pem |
| コードver. | ||
import requests
response = requests.get(
https://172.16.xx.xx/api/sample,
verify="/opt/certs/onprem-ca.pem"
)
ハマり1: CN=localhostの証明書
もらったpfxの中身がこれだった。
Subject: CN=localhost
Issuer: CN=localhost
TLS検証は「信頼するCAか」に加えて「証明書の名前(CN/SAN)とアクセス先の一致」もチェックする。
localhost宛に発行された証明書は、外からIPで叩いた時点で hostname mismatch になる。
再発行依頼した。
ハマり2: SANのDNS NameとIP Address
再発行されたら以下に。
DNS Name=172.16.xx.xx
DNS Name=localhost
NG。IPでアクセスした場合、検証ライブラリは「IP Address」タイプのエントリしか照合しない。
また再発行
IP Address=172.16.xx.xx
DNS Name=localhost ← ローカル確認用
運用時に気を付けること
証明書の有効期限