🔐

passlibを使うLambdaをWindowsでデプロイしてpasslib.exc.MissingBackendErrorとなったら

2023/09/18に公開

先に結論

Windows(WSL)でデプロイ時、Lambdaのアーキテクチャがx86_64だと、bcryptが使用できないというエラーが発生しました。Lambdaのアーキテクチャにarm64を使うと、エラーが発生しなくなりました。

現象

WindowsのWSLを使って開発しています。
passlib経由でbcryptを動かすFunctionを作成して、ローカルでは正しく動作しました。
ただし、Serverless Frameworkでデプロイして、Functionを動かすとpasslib.exc.MissingBackendError: bcrypt: no backends available -- recommend you install one (e.g. 'pip install bcrypt')というエラーが発生しました。

環境

Windows 11 バージョン 22H2 (OSビルド 22621.2283)
CPU 11th Gen Intel(R) Core(TM) i5-11400H @ 2.70GHz 2.69 GHz
WSL バージョン 1.2.5.0
カーネル バージョン 5.15.90.1
Ubuntu 20.04.5 LTS
serverless 3.34.0
serverless-python-requirements 6.0.0
Python 3.10
Pipenv 2023.7.11
passlib 1.7.4
bcrypt 4.0.1

エラー内容

  File "/var/task/app/password.py", line 41, in password
    hashed_password = pwd_context.hash(plain_password)
  File "/var/task/passlib/context.py", line 2258, in hash
    return record.hash(secret, **kwds)
  File "/var/task/passlib/utils/handlers.py", line 779, in hash
    self.checksum = self._calc_checksum(secret)
  File "/var/task/passlib/handlers/bcrypt.py", line 591, in _calc_checksum
    self._stub_requires_backend()
  File "/var/task/passlib/utils/handlers.py", line 2254, in _stub_requires_backend
    cls.set_backend()
  File "/var/task/passlib/utils/handlers.py", line 2156, in set_backend
    return owner.set_backend(name, dryrun=dryrun)
  File "/var/task/passlib/utils/handlers.py", line 2176, in set_backend
    raise default_error
passlib.exc.MissingBackendError: bcrypt: no backends available -- recommend you install one (e.g. 'pip install bcrypt')

コード

serverless.yml
service: serverless-example
frameworkVersion: '>=3.0.0 <4.0.0'

plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    usePipenv: false
    pipCmdExtraArgs:
      - '--platform'
      - 'manylinux2014_x86_64'
      - '--only-binary=:all:'
    dockerizePip: true

provider:
  name: aws
  stage: dev
  runtime: python3.10
  region: ap-northeast-1
  iamRoleStatements:
    - Effect: Allow
      Action:
        - ec2:DescribeInstances
      Resource: "*"
[packages]
passlib = {version = "*", extras = ["bcrypt"]}
...(略)
-i https://pypi.org/simple
...(略)
bcrypt==4.0.1
passlib[bcrypt]==1.7.4
...(略)

デプロイ方法

$ pipenv requirements > requirements.txt
$ npx sls deploy --aws-profile hoge

調査

requirements.txtにもbcryptモジュールは含まれていました。もちろんLambdaデプロイのためののzipファイルに、bcryptモジュールは含まれていました。なぜ動かないのかわからず。

$ ls serverless-example | egrep 'passlib|bcrypt'
bcrypt
bcrypt-4.0.1.dist-info
passlib
passlib-1.7.4.dist-info

macでデプロイしてLambdaを動かしてみると、エラーが発生しませんでした。なので、使用しているOSによって起こる問題なのかもしれません。

対策

試しにLambdaのアーキテクチャをarm64に変更して再現するのか確認してみたら、エラーが発生しませんでした!もしこのエラーが発生するときはアーキテクチャを変更してもいいかもしれません(arm64の方が処理速度が速いし)
ただ、Pipenvの問題なのか、serverless-python-requirementsのプラグインの問題なのか、それとも別の問題なのか、根本原因はわかりませんでした。x86_64でエラーを回避する方法は見つけられなかったので、もしわかる方がいればコメントお願いします。

arm64に変更したコード

serverless.yml
service: serverless-example
frameworkVersion: '>=3.0.0 <4.0.0'

plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    usePipenv: false
    pipCmdExtraArgs:
      - '--platform'
      - 'manylinux2014_aarch64'
      - '--only-binary=:all:'
    dockerizePip: true

provider:
  name: aws
  architecture: arm64
  stage: dev
  runtime: python3.10
  region: ap-northeast-1
  iamRoleStatements:
    - Effect: Allow
      Action:
        - ec2:DescribeInstances
      Resource: "*"

参考URL

https://www.repost.aws/questions/QUa3HaSbEeTYyqRivLpi3InQ/passlib-exc-missingbackenderror-bcrypt-no-backends-available-recommend-you-install-one-e-g-pip-install-bcrypt
https://stackoverflow.com/questions/56720614/bcrypt-does-not-work-on-lambda-serverless

Discussion