Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
AWS Lambda function for forwarding Alexa Intent requests to Home Assistant
# -*- coding: utf-8 -*-
import os
import json
import logging
import urllib3
_debug = bool(os.environ.get('DEBUG'))
_logger = logging.getLogger('HomeAssistant-Intents')
_logger.setLevel(logging.DEBUG if _debug else logging.INFO)
def lambda_handler(event, context):
"""Handle incoming Alexa directive."""
_logger.debug('Event: %s', event)
base_url = os.environ.get('BASE_URL')
assert base_url is not None, 'Please set BASE_URL environment variable'
try:
token = event.get('session', {}).get('user', {}).get('accessToken')
except AttributeError:
token = None
if token is None and _debug:
token = os.environ.get('LONG_LIVED_ACCESS_TOKEN')
assert token, 'Could not get access token'
verify_ssl = not bool(os.environ.get('NOT_VERIFY_SSL'))
http = urllib3.PoolManager(
cert_reqs='CERT_REQUIRED' if verify_ssl else 'CERT_NONE',
timeout=urllib3.Timeout(connect=2.0, read=10.0)
)
response = http.request(
'POST',
'{}/api/alexa'.format(base_url),
headers={
'Authorization': 'Bearer {}'.format(token),
'Content-Type': 'application/json',
},
body=json.dumps(event).encode('utf-8'),
)
if response.status >= 400:
return {
'event': {
'payload': {
'type': 'INVALID_AUTHORIZATION_CREDENTIAL'
if response.status in (401, 403) else 'INTERNAL_ERROR',
'message': response.data.decode("utf-8"),
}
}
}
return json.loads(response.data.decode('utf-8'))
@lpomfrey
Copy link
Author

lpomfrey commented Dec 28, 2019

Yea, that's an Amazon requirement:

Note that the account linking URL must be a HTTPS URL on port 443, with a certificate from an Amazon approved CA authority (https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReport).
https://forums.developer.amazon.com/articles/38610/alexa-debugging-account-linking.html

It's actually noted on the Smart Home docs but not on the Custom Intent ones. I've submitted a pull request to clarify that on both.

@scyto
Copy link

scyto commented Feb 21, 2022

The NOT_VERIFY_SSL env var doesn't seem to work at all (and I expect the same is true for debug)
It doesn't matter how I set the environment variable it doesn't change the SSL behavior.

My belief based on some googling is that environment variables are NOT booleans as such all this code tests for is the presence of envvar.
But i am not sure and too code illiterate to know how to fix (i tried several of the suggestions in the link)

    verify_ssl = not bool(os.environ.get('NOT_VERIFY_SSL'))

    http = urllib3.PoolManager(
        cert_reqs='CERT_REQUIRED' if verify_ssl else 'CERT_NONE',
        timeout=urllib3.Timeout(connect=2.0, read=10.0)

i worked around this by hard coding it to certs required

#    verify_ssl = not bool(os.environ.get('NOT_VERIFY_SSL'))

    http = urllib3.PoolManager(
        cert_reqs='CERT_REQUIRED',  #if verify_ssl else 'CERT_NONE',
        timeout=urllib3.Timeout(connect=2.0, read=10.0)

---edit-- oh i see
all the code does is detect if the var is present, it doesn't care what it is set to to.
This means the docs at here are wrong.

NOT_VERIFY_SSL (optional): set to True to ignore the SSL issue, if you don’t have a valid SSL certificate or you are using self-signed certificate.
DEBUG (optional): set to True to log debugging messages.

one needs to REMOVE NOT_VERIFY_SSL to turn on SSL checking and add it to turn it off, what ever it is set to is irrelevant (i couldn't for the life of me figure out why when i set to false it did nothing, lol)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment