この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
AWS Lambdaの最新のランタイムではAmazon Linux 2が使われていて、OpenSSLパッケージを見つける事ができません。このような環境でOpenSSLコマンドを使う方法を説明します。
OpenSSLコマンドの確認
ランタイムがPython3.8(Amazon Linux 2)のLambda関数でOpenSSLコマンドを実行してみました。
lambda_function.py
import subprocess
def lambda_handler(event, context):
output = subprocess.run(['openssl', 'version'], stdout=subprocess.PIPE)
print(output.stdout.decode())
コンソールにコマンドが見つからない場合のエラーが出力されます。
{
"errorMessage": "[Errno 2] No such file or directory: 'openssl'",
"errorType": "FileNotFoundError",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 4, in lambda_handler\n output = subprocess.run(['openssl', 'version'], stdout=subprocess.PIPE)\n",
" File \"/var/lang/lib/python3.8/subprocess.py\", line 489, in run\n with Popen(*popenargs, **kwargs) as process:\n",
" File \"/var/lang/lib/python3.8/subprocess.py\", line 854, in __init__\n self._execute_child(args, executable, preexec_fn, close_fds,\n",
" File \"/var/lang/lib/python3.8/subprocess.py\", line 1702, in _execute_child\n raise child_exception_type(errno_num, err_msg, err_filename)\n"
]
}
ランタイムがPython3.7(Amazon Linux)のLambda関数では、OpenSSLのバージョンが出力されます。
OpenSSL 1.0.2k-fips 26 Jan 2017
AWS LambdaのランタイムとOS
OSにAmazon Linux 2を使用しているランタイムでOpenSSLを利用するためには、EC2のインスタンスからOpenSSLのバイナリを取得して、Lambdaにデプロイする必要があります。
Node.jsのランタイム
名前 | 識別子 | AWS SDK for JavaScript | オペレーティングシステム |
---|---|---|---|
Node.js 12 | nodejs12.x |
2.585.0 | Amazon Linux 2 |
Node.js 10 | nodejs10.x |
2.585.0 | Amazon Linux 2 |
Pythonのランタイム
名前 | 識別子 | AWS SDK for Python | オペレーティングシステム |
---|---|---|---|
Python 3.8 | python3.8 |
boto3-1.10.34 botocore-1.13.34 | Amazon Linux 2 |
Python 3.7 | python3.7 |
boto3-1.10.34 botocore-1.13.34 | Amazon Linux |
Python 3.6 | python3.6 |
boto3-1.10.34 botocore-1.13.34 | Amazon Linux |
Python 2.7 | python2.7 |
boto3-1.10.34 botocore-1.13.34 | Amazon Linux |
OpenSSLのバイナリを取得
EC2でAmazon Linux 2 AMIのインスタンスを立ち上げます。
インスタンスにSSHで接続して、OpenSSLパッケージのパスを確認します。
$ which openssl
/usr/bin/openssl
SCPでローカルに保存します。
$ mkdir openssl
$ scp -i <鍵ファイルのパス> ec2-user@xxx.xxx.xxx.xxx:/usr/bin/openssl ./openssl
Lambdaレイヤーを作成
先ほどローカルに保存したOpenSSLのバイナリをZIPファイルにします。
$ zip -r openssl.zip openssl/
Lambdaレイヤーを作成します。
Lambda関数を作成
新しくLambda関数を作成して、Lambdaレイヤーを設定します。
LambdaレイヤーのPATHを追加して、OpensSSLコマンドを実行します。
lambda_function.py
import os
import subprocess
os.environ['PATH'] = os.environ['PATH'] + ':/opt/openssl'
def lambda_handler(event, context):
output = subprocess.run(['openssl', 'version'], stdout=subprocess.PIPE)
print(output.stdout.decode())
OpenSSLのバージョンが出力されます。
OpenSSL 1.0.2k-fips 26 Jan 2017
まとめ
Lambda関数で秘密鍵や証明書を作成しようとした際に、最新のランタイムでOpenSSLコマンドが使えなくて困りました。他にもOS依存のパッケージをLambdaで使いたい場合は、Lambdaと同じOS(Amazon Linux)をEC2で立ち上げて、バイナリをLambdaレイヤーにデプロイする事で実行できるようになるかと思います。