mirror of
https://github.com/GSA/notifications-api.git
synced 2025-12-23 17:01:35 -05:00
The CBC Proxy is essentially a lambda function which we invoke with various arguments. A way in which this can fail is that the notifications-api app invoking the function may not be able, any longer, to invoke the function. This could be caused by, for example: * an egress restriction preventing access to eu-west-2.lambda.amazonaws.com * a network partition preventing access to eu-west-2.lambda.amazonaws.com * the app's credentials have been rotated or revoked If we invoke a simple "canary" lambda function for which the app should have access to invoke, and check it for failures, we will know quickly if something is likely to be broken. This is especially important for cell broadcasts compared to email/SMS because we always have a baseline of traffic for email/SMS, and so any failure is observed almost immediately. This is not true for CB where we may expect to only see one CB message every week/month/quarter/year, as opposed to every minute or second for email/SMS. Signed-off-by: Toby Lorne <toby.lornewelch-richards@digital.cabinet-office.gov.uk> Co-authored-by: Pea <pea.tyczynska@digital.cabinet-office.gov.uk>
122 lines
3.2 KiB
Python
122 lines
3.2 KiB
Python
import json
|
|
|
|
import boto3
|
|
|
|
# The variable names in this file have specific meaning in a CAP message
|
|
#
|
|
# identifier is a unique field for each CAP message
|
|
#
|
|
# headline is a field which we are not sure if we will use
|
|
#
|
|
# description is the body of the message
|
|
|
|
# areas is a list of dicts, with the following items
|
|
# * description is a string which populates the areaDesc field
|
|
# * polygon is a list of lat/long pairs
|
|
#
|
|
# references is a whitespace separated list of message identifiers
|
|
# where each identifier is a previous sent message
|
|
# ie a Cancel message would have a unique identifier but have the identifier of
|
|
# the preceeding Alert message in the references field
|
|
|
|
|
|
# Noop = no operation
|
|
class CBCProxyNoopClient:
|
|
|
|
def init_app(self, app):
|
|
pass
|
|
|
|
def send_canary(
|
|
self,
|
|
identifier,
|
|
):
|
|
pass
|
|
|
|
def create_and_send_broadcast(
|
|
self,
|
|
identifier, headline, description, areas
|
|
):
|
|
pass
|
|
|
|
# We have not implementated updating a broadcast
|
|
def update_and_send_broadcast(
|
|
self,
|
|
identifier, references, headline, description, areas
|
|
):
|
|
pass
|
|
|
|
# We have not implemented cancelling a broadcast
|
|
def cancel_broadcast(
|
|
self,
|
|
identifier, references, headline, description, areas
|
|
):
|
|
pass
|
|
|
|
|
|
class CBCProxyClient:
|
|
|
|
def init_app(self, app):
|
|
self._lambda_client = boto3.client(
|
|
'lambda',
|
|
region_name='eu-west-2',
|
|
aws_access_key_id=app.config['CBC_PROXY_AWS_ACCESS_KEY_ID'],
|
|
aws_secret_access_key=app.config['CBC_PROXY_AWS_SECRET_ACCESS_KEY'],
|
|
)
|
|
|
|
def send_canary(
|
|
self,
|
|
identifier,
|
|
):
|
|
payload_bytes = bytes(json.dumps({
|
|
'identifier': identifier,
|
|
}), encoding='utf8')
|
|
|
|
result = self._lambda_client.invoke(
|
|
FunctionName='canary',
|
|
InvocationType='RequestResponse',
|
|
Payload=payload_bytes,
|
|
)
|
|
|
|
if result['StatusCode'] > 299:
|
|
raise Exception('Could not invoke lambda')
|
|
|
|
if 'FunctionError' in result:
|
|
raise Exception('Function exited with unhandled exception')
|
|
|
|
def create_and_send_broadcast(
|
|
self,
|
|
identifier, headline, description, areas,
|
|
):
|
|
payload_bytes = bytes(json.dumps({
|
|
'identifier': identifier,
|
|
'headline': headline,
|
|
'description': description,
|
|
'areas': areas,
|
|
}), encoding='utf8')
|
|
|
|
result = self._lambda_client.invoke(
|
|
FunctionName='bt-ee-1-proxy',
|
|
InvocationType='RequestResponse',
|
|
Payload=payload_bytes,
|
|
)
|
|
|
|
if result['StatusCode'] > 299:
|
|
raise Exception('Could not invoke lambda')
|
|
|
|
if 'FunctionError' in result:
|
|
raise Exception('Function exited with unhandled exception')
|
|
|
|
# We have not implementated updating a broadcast
|
|
def update_and_send_broadcast(
|
|
self,
|
|
identifier, references, headline, description, areas,
|
|
):
|
|
pass
|
|
|
|
# We have not implemented cancelling a broadcast
|
|
def cancel_broadcast(
|
|
self,
|
|
identifier, references, headline, description, areas,
|
|
):
|
|
pass
|