Miserlou / Zappa

Serverless Python
https://blog.zappa.io/
MIT License
11.89k stars 1.2k forks source link

SigverError: Can't find ['xmlsec1'] #1374

Closed robertruetz closed 6 years ago

robertruetz commented 6 years ago

Context

I'm trying to use Zappa to deploy an API Gateway/Lambda combination that does SAML authentication and then runs some Python code to redirect to a URL. The SAML Auth part is failing with a SigverError: Can't find ['xmlsec1'].

Expected Behavior

User hits a tile in an IdP which targets my endpoint. The SAML assertion is parsed and authenticated. Then the user is redirected to a generated URL.

Actual Behavior

SAML Authentication fails because the lambda can't load the xmlsec1 library.

Things I've tried

Steps to Reproduce

  1. Create a Flask app that uses pysaml2 which requires xmlsec
  2. Deploy app to AWS with zappa.
  3. Hit your endpoint and watch the failsauce.

Your Environment

robertruetz commented 6 years ago

I was ignoring the soft error in the standard output noting that my virtual env and my project had the same name. I set up yet another virtualenv with a different name than the project and tried installing and deploying again. Same result.

robertruetz commented 6 years ago

Looking through the code for pysaml2, I ran across this comment at the top """ Functions connected to signing and verifying. Based on the use of xmlsec1 binaries and not the python xmlsec module. """. This makes me think that the problem here is that zappa is including the python xmlsec module but not the libxmlsec1 binaries and thus pysaml2 fails looking for that binary.

madalinoprea commented 6 years ago

Hi @robertruetz,

I had the same issue when trying to use python-saml and the solution that worked for me was to add libxmlsec binaries to AWS Lambda package's lib folder. From my findings, libraries referenced by python-saml are not available in AWS Lambda execution environment.

cp /usr/lib64/libxmlsec1-openssl.so.1 lib/
cp /usr/lib64/libxmlsec1-openssl.so lib/
cp /usr/lib64/libxmlsec1.so.1 lib/

LOGNAME=jenkins zappa package LATEST -o "../${PACKAGE_FILENAME}" --disable_progress

To generate binaries compatible for AWS I'm using a customised Docker image lambci/lambda:build-python2.7. Probably you could remove openldap-devel and mysql-devel packages.

FROM lambci/lambda:build-python2.7

RUN yum -y update && rpm --rebuilddb \
    && yum install -y yum-plugin-ovl openldap-devel libxml2-devel mysql-devel

# Using rpms from https://github.com/onelogin/python-saml/issues/30
RUN yum -y update && rpm --rebuilddb \ 
    && curl --silent -O http://vault.centos.org/6.5/cr/x86_64/Packages/xmlsec1-1.2.20-4.el6.x86_64.rpm \
    && curl --silent -O http://vault.centos.org/6.5/cr/x86_64/Packages/xmlsec1-devel-1.2.20-4.el6.x86_64.rpm \
    && curl --silent -O http://vault.centos.org/6.5/cr/x86_64/Packages/xmlsec1-openssl-1.2.20-4.el6.x86_64.rpm \
    && curl --silent -O http://vault.centos.org/6.5/cr/x86_64/Packages/xmlsec1-openssl-devel-1.2.20-4.el6.x86_64.rpm \
    && ls -al \
    && yum install -y xmlsec1-1.2.20-4.el6.x86_64.rpm xmlsec1-devel-1.2.20-4.el6.x86_64.rpm \
        xmlsec1-openssl-1.2.20-4.el6.x86_64.rpm xmlsec1-openssl-devel-1.2.20-4.el6.x86_64.rpm \
    && yum install -y libtool-ltdl-devel

RUN sed -i 's/LIBLTDL=1 -I/LIBLTDL=1 -DXMLSEC_NO_SIZE_T -I/' /usr/bin/xmlsec1-config
robertruetz commented 6 years ago

@madalinoprea, thanks for your comment. I went through building the dependencies in a Docker container and then copying them out to my local lib. After adding the local dependency dirs to the Lambda execution PATH, I've gotten to the next error. Now I'm dealing with permissions issues. I believe based on the traceback that xmlsec is trying to parse the SAML XML which I'm assuming is saved to a local temp directory that the script doesn't have permissions to. However, you got me past the missing dependencies error. Thanks!

robertruetz commented 6 years ago

I can't seem to get past the permissions issue. The problem appears to be that saml2 is trying to open a subprocess calling xmlsec1, but it doesn't have permission to execute xmlsec1.

LOG:

I think the real problem here is that I don't know where the dependencies should go. Currently I'm adding the dependency directory to the lambda PATH variable, and it can find xmlsec1, but it can't execute it. Is there some agreed upon location where the compiled binaries should be for permissions to work out?

madalinoprea commented 6 years ago

For our SAML implementation we're using python-saml package which relies on xmlsec bindings instead of xmlsec binary so we didn't get these errors.

These docs https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html lists all env variables and different locations that python code can use. For example, LD_LIBRARY_PATH points to lambda's lib folder.

Did you had to add xmlsec1 binary to AWS Lamda package? I assume this binary is not available in AWS Lambda because was compiled by yum packages installed in docker image.

Maybe try to create a test script to determine if file exists, is executable, etc by running in AWS Lambda environment os.stat on xmlsec1 binary location, and start subprocess xmlsec1 --version.

I'm seeing that pysaml is trying to use /var/task/dependencies/lib/xmlsec1, but I'm not sure if found location is really valid.

I see that pysaml2 can be configured to use a specific xmlsec binary via xmlsec_binary configuration (https://pysaml2.readthedocs.io/en/latest/examples/sp.html), for example use something like ${LAMBDA_TASK_ROOT}/lib/xmlsec1.

robertruetz commented 6 years ago

@madalinoprea, thanks again for your input. You got me moving in the correct direction. I was making a few errors, the first of which was not more thoroughly reading the documentation on both zappa and pysaml2. No excuse for that. I added the config points you mentioned and then managed to get my lambda to at least attempt to verify my request.

Lessons learned:

Thanks!

jethomas84 commented 1 year ago

@robertruetz - I have come to this long closed topic in search of much needed help. Trying to get a Django/zappa project deployed as a lambda with SAML2/Okta support. Running into this exact issue. I have used docker images, copied the .so files to many different locations in the solution, declared the "xmlsec_binary" location in config, really tried everything and still it cannot find xmlsec1. How did you actually solve this. Desperate for any insight, thank you!

souravjamwal77 commented 1 year ago

Hi @jethomas84, I will try to create a docker image for this. Maybe I will reply in 2 days as I'm traveling right now.

souravjamwal77 commented 1 year ago

You can also join our Slack channel Here

jethomas84 commented 1 year ago

@souravjamwal77 thank you:

Using Zappa to deploy Django with a SAML2 package (which requires xmlsec1). Here are the steps I tried:

  1. Got one of the official docker images that represents AWS Lambda (Lambci?)
  2. Virtual environment set up, all packages and dependencies installed (including xmlsec)
  3. Copied .so files over to lib folder, copied them into multiple places...
  4. tried setting xmlsec_binary in the saml settings as well to /var/task/lib
  5. Deploy via zappa - try saml login and SigverError: Can't find ['xmlsec1']

I've tried so many different angles and packages - sort of at a loss.

souravjamwal77 commented 1 year ago

Let me try it once using debian based images and see if it works.