2

I'm currently having an issue with my python code, this code generates a Cloud Front signed URL and prints it. I have a virtual environment in VS Code and it works fine but as soon as I upload it to lambda I get the error: "errorMessage": "No module named '_cffi_backend""

I have tried :

pip install -t $PWD cffi

pip install -t $PWD cryptography

zipping them into a .zip file and uploading it to lambda to meet the requirements, and I've also zipped all the packages within my virtual environment that has working dependencies.

How can I resolve this issue? I need this to be in lambda, and I've reinstalled cffi before aswell.

import datetime

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from botocore.signers import CloudFrontSigner


def rsa_signer(message):
    with open('key.pem', 'rb') as key_file:
        private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None,
            backend=default_backend()
        )
        print (message)
    return private_key.sign(message, padding.PKCS1v15(), hashes.SHA1())

def lambda_handler(event, context):

    key_id = 'APKAJSKEXampleKNQ'
    url = 'https://example.com/example.html'
    expire_date = datetime.datetime(2021, 1, 1)

    cloudfront_signer = CloudFrontSigner(key_id, rsa_signer)

    # Create a signed url that will be valid until the specfic expiry date
    # provided using a canned policy.
    signed_url = cloudfront_signer.generate_presigned_url(
        url, date_less_than=expire_date)
    print(signed_url)

{
  "errorMessage": "No module named '_cffi_backend'",
  "errorType": "ModuleNotFoundError",
  "stackTrace": [
    "  File \"/var/task/why.py\", line 31, in lambda_handler\n    url, date_less_than=expire_date)\n",
    "  File \"/var/runtime/botocore/signers.py\", line 344, in generate_presigned_url\n    signature = self.rsa_signer(policy)\n",
    "  File \"/var/task/why.py\", line 15, in rsa_signer\n    backend=default_backend()\n",
    "  File \"/var/task/cryptography/hazmat/backends/__init__.py\", line 15, in default_backend\n    from cryptography.hazmat.backends.openssl.backend import backend\n",
    "  File \"/var/task/cryptography/hazmat/backends/openssl/__init__.py\", line 7, in <module>\n    from cryptography.hazmat.backends.openssl.backend import backend\n",
    "  File \"/var/task/cryptography/hazmat/backends/openssl/backend.py\", line 109, in <module>\n    from cryptography.hazmat.bindings.openssl import binding\n",
    "  File \"/var/task/cryptography/hazmat/bindings/openssl/binding.py\", line 14, in <module>\n    from cryptography.hazmat.bindings._openssl import ffi, lib\n"
  ]
}
D3vRandom
  • 155
  • 1
  • 1
  • 12

1 Answers1

4

I read the source code for the "boto" Cloud Front Signer and found that all functions are built-in. There's no need to use "cryptography.hazmat".

I switched the above code to something a bit more simple.

from boto.cloudfront.distribution import Distribution
from boto.cloudfront import CloudFrontConnection
from botocore.signers import CloudFrontSigner
import datetime
import rsa

def rsa_signer(message):
    private_key = open('key.pem', 'r').read()
    return rsa.sign(message, rsa.PrivateKey.load_pkcs1(private_key.encode('utf8')),'SHA-1')

def lambda_handler(event, context):
    url = "https://Example.com/Register.html"                                                                                                                                                                      
    expire_date = datetime.datetime(2021, 1, 1)
    key_id = 'APKAJSEXAMPLENXQ'
    cf_signer = CloudFrontSigner(key_id, rsa_signer)
    signed_url = cf_signer.generate_presigned_url(url, date_less_than=expire_date)
    print(signed_url)

For anyone wondering this is how to properly generate a Cloud Front PresignedUrl using python. Make sure to package "boto" and "rsa" into your zip file when uploading to lambda.

D3vRandom
  • 155
  • 1
  • 1
  • 12
  • 1
    Oh man, I wish I had seen this before I was using python to create signed url's for my website as well. But I was always getting access denied error. So to mitigate that I went with the node.js approach. I will be trying out your method as well since it seems pretty neat. Thanks so much.! – flyiinhigh Jul 22 '20 at 15:45