Python Crypto not found in bundle

Hi,

I’m trying to use pycryptodome to do some encryption in the python plugin.

In the python code I imported the following:

import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes

After I bundle it using:

docker run --rm -w "/tmp" -v $(pwd):/tmp --entrypoint "/bin/sh" -it tykio/tyk-gateway:$IMAGETAG -c '/opt/tyk-gateway/tyk bundle build -y'

I’m getting this error:

tyk-gateway-docker-tyk-gateway-1  | time="Jan 20 09:59:40" level=error msg="Your bundle doesn't contain 'Crypto'" prefix=python
tyk-gateway-docker-tyk-gateway-1  | time="Jan 20 09:59:40" level=error msg="Middleware initialization error: No module named 'Crypto'" prefix=python

How should I go about doing it? What did I miss?

Best regards.

Based on the error message, you will need to vendor any dependencies within your bundle. There is an example here using Python 3.7 however you would need to change it based on your environment.

Hi @Olu

I tried the steps provided in the link u provided. But I’m kinda lost in terms of the instruction. Appreciate if you could kindly guide me through.

It’s as simple as creating a requirements.txtfile and runningpip3 install -r requirements.txt --prefix vendor`

I’m running tyk in a docker env. Where do I place this requirement.txt? In the plugin bundle folder?

You may need to manually add the vendor directory to the bundle.zip with something like this:
zip -ur ${bundle}.zip vendor/

When I setup python venv in the bundle folder and install the library. It is residing in venv/lib/python3.7/site-packages/Crypto so how does this translate to the command above. I tried to put zip -ur bundle.zip venv/ and it does not work.

Also be aware that you need to be careful about loading these import within your python scripts.
I use this sort of thing

bundle_dir = os.path.abspath(os.path.dirname(__file__))
for lib_dir in [ 'vendor/lib/python3.7/site-packages/' ]:
  vendor_dir = os.path.join(bundle_dir, lib_dir)
  sys.path.append(vendor_dir)

import jwt

I tried the above code and change to:


import os
import sys
bundle_dir = os.path.abspath(os.path.dirname(__file__))
tyk.log("bundle_dir = ({0})".format(bundle_dir),"debug")
for lib_dir in [ 'venv/lib/python3.7/site-packages/']:
    vendor_dir = os.path.join(bundle_dir, lib_dir)
    tyk.log("bundle_dir = ({0},({1}))".format(lib_dir, vendor_dir),"debug")
    sys.path.append(vendor_dir)

import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes

Would appreciate if any help/advise given. Thanks.

Hi,

I had manage to figure out and got the things to work. For the community let me put it down and hope it can help others.

I’m using tyk gateway in dockers and using Python Plugin-in bundles.

  1. in the folder where the plugin bundle file middleware.py, manifest.json reside, you can either create requirement.txt (simply) or simply key in the command as below.

    pip3 install pycryptodome --prefix vendor

  2. The command will install the lib for the package into a folder call vendor.

  3. Insert the code provided by @Pete from another post in the python file that requires the new library. No change in the code needed, just copy and paste it in. Create the plugin bundle.

    bundle_dir = os.path.abspath(os.path.dirname(__file__))
    for lib_dir in [ 'vendor/lib/python3.7/site-packages/' ]:
         vendor_dir = os.path.join(bundle_dir, lib_dir)
         sys.path.append(vendor_dir)
    
  4. With your bundle.zip created, in the same directory where vendor folder and bundle.zip are, proceed to key in the command below.

    zip -ur bundle.zip vendor/
    5.The zip command will add the vendor folder into the existing bundle.zip package.

  5. Then remove existing plugin bundle for Tyk Gateway before starting the docker image using in the tykgateway folder:

    rm -r middleware/bundles

For step 2, I found out that it is important to install in the right environment to get the correct file. I’m developing it on a Mac and the installation will not include files that are meant for other platforms. Tyk dockers are based on Debian/Linux, hence to work around it I installed a Ubuntu VMware and install the lib and copy over to Mac for bundling.

1 Like

Great work @kamikazane

medalgiphy

We have granted you the badge Percival. You can find your new badge in the badges tab of your profile page. Big respect for persevering and giving back to the community :metal:

1 Like

Hi @kamikazane @Olu,
I tried @kamikazane’s solution and I am facing the error: ‘’'Cannot load native module ‘Crypto.Cipher._raw_ecb’: Not found ‘_raw_ecb.cpython-311-x86_64-linux-gnu.so’, Not found ‘_raw_ecb.abi3.so’, Not found ‘_raw_ecb.so’". If you have any ideas that would be greatly appreciated.

I’m not sure about your setup, but from the look of it I think you are facing the same problem I had when I tried running it off Dockers from my macOS.

As mentioned in step 2. Tyk dockers are based on Linux/Debian so there is a need to get the correct library files that is specific to your host OS. I did a Ubuntu VM on macOS just to get those affected files. You probably will have to do the same.