7

I am writing a lambda function with an intent that uses requests to pull information from a Wolfram CloudObject. Here is the relevant part of the code:

from __future__ import print_function
import requests

.
.
.

def on_intent(intent_request, session):
    print("on_intent requestID=" + intent_request['requestID'] + ", sessionID=" + session['sessionId'])

    intent = intent_request['intent']
    intent_name = intent_request['intent']['name']

    # Dispatch to skill's intent handlers

    if intent_name == "GetEvent":
         return call_wolfram(intent, session)
    elif intent_name == "AMAZON.HelpIntent":
         return get_welcome_response()
    elif intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent":
         return handle_session_end_request()
    else:
         raise ValueError("Invalid intent")

.
.
.

# Functions that control skill's behavior

def call_wolfram(intent, session):
    url = "https://path-to-cloud-object"
    query = {'string1': 'VESSEL', 'string2': 'EVENT', 'RelString': 'TRIGGERED'}
    r = requests.get(url, params=query)
    session_attributes = {"r_result": r}
    speech_output = "Congrats, dummy! It worked"
    card_title = "Query"
    should_end_session = True
    return build_response({}, build_speechlet_response(card_title, speech_output, None, should_end_session)

Most of the rest of the code follows the MyColorIs example template given by AWS with minimal changes. When the lambda function is tested, the error message gives me a json file with stackTrace; I've narrowed down the issue to the lines of code r = requests.get() and session_attributes = {}, because when commented out, the lambda execution is successful. This is my first project with python, so I am new to the language as well. For good measure, here is the error message I get after lambda executes:


{
  "stackTrace": [
   [
     "/var/task/query_lambda.py",
     27,
     "lambda_handler",
     "return on_intent(event['request'], event['session'])"
   ],
   [
     "/var/task/query_lambda.py",
     65,
     "on_intent",
     "return call_wolfram(intent, session)"
   ],
   [
     "/var/task/query_lambda.py",
     113,
     "call_wolfram",
     "r = requests.get(url, params=query)"
   ],
   [
     "/var/task/requests/api.py",
     71,
     "get",
     "return request('get', url, params=params, **kwargs)"
   ],
   [
     "/var/task/requests/api.py",
     57,
     "request",
     "return session.request(method=method, url=url, **kwargs)"
   ],
   [
     "/var/task/requests/sessions.py",
     475,
     "request",
     "resp = self.send(prep, **send_kwargs)"
   ],
   [
     "/var/task/requests/sessions.py",
     585,
     "send",
     "r = adapter.send(request, **kwargs)"
   ],
   [
     "/var/task/requests/adapters.py",
     477,
     "send",
     "raise SSLError(e, request=request)"
    ]
  ],
    "errorType": "SSLError",
    "errorMessage": "[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify    failed (_ssl.c:590)"
}
Lame-Ov2.0
  • 201
  • 1
  • 3
  • 11
  • this is an SSL certificate error. try updating `certifi` with pip to make sure the certificates are up to date (in a console, `pip install certifi --upgrade`) – Corley Brigman Jun 28 '16 at 16:31
  • @CorleyBrigman I did `sudo -H pip install certifi --upgrade` and was told the requirement was already up to date. – Lame-Ov2.0 Jun 28 '16 at 18:17
  • does the URL have to be `https`? if it does, can you get to it from a web browser in the same environment you are doing the request? you may have to install a custom certificate or something... – Corley Brigman Jun 28 '16 at 18:34
  • 1
    also, not a duplicate, but some information here may be useful: http://stackoverflow.com/questions/22027418/openssl-python-requests-error-certificate-verify-failed – Corley Brigman Jun 28 '16 at 18:36
  • @CorleyBrigman yes, the url has to be `https`. Sorry, I'm not sure what you mean by "a web browser in the same environment [I am] doing the request", could you please explain that? – Lame-Ov2.0 Jun 28 '16 at 18:59
  • Also to note, just in case it's helpful, I don't have an `SSLError` when making this same request from my local machine with a small .py script – Lame-Ov2.0 Jun 28 '16 at 19:03

2 Answers2

9

The lambda environment does not include the certifi module, unless you upload it with your function.

I would do this:

cd <directory with your lambda>
pip install certifi -t .
zip ../lambda *

Then upload the ../lambda.zip to Amazon.

Sean Summers
  • 2,514
  • 19
  • 26
  • Holy heck, this was an awesome tip thanks! In my case I was packaging up only `*.py` and skipping over the `.pem` files that were needed for this to work correctly. – scorpiodawg Dec 12 '16 at 23:02
3

You can read more about requests' use of certificates here:

http://docs.python-requests.org/en/master/user/advanced/

There are two ways to get around this problem:

  • Find the certificate that you are missing, and get it installed on the system that's failing.
  • Ignore the certificates altogether by passing verify=False to requests.get:

    r = requests.get(url, params=query, verify=False)

The second method is quicker, but less secure; that may or may not matter for your intended use.

Corley Brigman
  • 11,633
  • 5
  • 33
  • 40
  • Thanks, this fixed the issue for the time being while I waited for Wolfram to get back to me with their intermediate CA – Lame-Ov2.0 Jun 29 '16 at 18:43