dockergoogle-cloud-runpipenvjosepython-jose

Uploading python-jose to cloud run fails


So I've created this Flask-app which is going to serve as my backend for a custom app.

To handle the creation of JWT-tokens, I've decided upon using an encrypted JWS (a JWS inside of a JWE). For this, I've chosen to use the python-jose package. I've tried JWCrypto before but it failed locally for me in regards to JWK (locally) and couldn't wrap my head around it.

After setting up and testing my app locally, the functions I'm using are working perfectly. However, after uploading them to cloud run (with a success-build), the encryption fail. Stating this message:

File "/usr/local/lib/python3.9/site-packages/jose/jwk.py", line 78, in construct raise JWKError("Unable to find an algorithm for key: %s" % key_data) jose.exceptions.JWKError: Unable to find an algorithm for key: secret-for-stack-overflow

This is the function handling the encryption:

def encode_token(payload):
    jws_secret = "xxxxxxx"
    jwe_key = "xxxxxx"

    signed_token = jws.sign(payload, jws_secret, algorithm='HS256')
    encrypted_signed_token = jwe.encrypt(signed_token, jwe_key, algorithm='dir', encryption='A128GCM')
    
    return encrypted_signed_token

I know I'm sharing keys and secrets above but my app doesn't connect to a db yet or do anything useful + I'm going to change them after I fix it. So it's ok :)

And this is my dockerfile:

# Use the official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.9-slim

# Allow statements and log messages to immediately appear in the Knative logs
ENV PYTHONUNBUFFERED True

# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./

# Install production dependencies.
RUN pip install --no-cache-dir -r requirements.txt

# Run the web service on container startup. Here we use the gunicorn
# webserver, with one worker process and 8 threads.
# For environments with multiple CPU cores, increase the number of workers
# to be equal to the cores available.
# Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling.
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

And finally, this is my requirements.txt (autogenerated via pipenv):

#
# These requirements were autogenerated by pipenv
# To regenerate from the project's Pipfile, run:
#
#    pipenv lock --requirements
#

-i https://pypi.org/simple
click==8.1.3; python_version >= '3.7'
ecdsa==0.17.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'
flask==2.1.2
gunicorn==20.1.0
importlib-metadata==4.11.4; python_version < '3.10'
itsdangerous==2.1.2; python_version >= '3.7'
jinja2==3.1.2; python_version >= '3.7'
markupsafe==2.1.1; python_version >= '3.7'
pyasn1==0.4.8
python-jose==3.3.0
rsa==4.8; python_version >= '3.6' and python_version < '4'
setuptools==62.3.3; python_version >= '3.7'
six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
werkzeug==2.1.2; python_version >= '3.7'
zipp==3.8.0; python_version >= '3.7'

I just don't get how this can work on my machine but not on GCP. On my local machine (Pipenv shell) I get the JWE returned back perfectly. My local python version is 3.8.3, but I've tried using 3.8 and 3.10 as well in the Dockerfile with the same unfortunate result when deployed.

Anyone knows why this might happen and what a fix could be? If you could point me to an alternative solution (if above is not fixable), I would be eternally greatful :)


Solution

  • Problem solved!

    Upgraded local dev-environment to Python 3.10 and deleted python-jose and instead installed python-jose[cryptography].