An AWS Lambda for emailing monthly totals to tagged resource owners
This lambda will query Cost Explorer for our Owner Email cost category, query Synapse for the members of Team Sage, and email a monthly total to internal Sage users who have been tagged as resource owners.
Parameter Name | Allowed Values | Default Value | Description |
---|---|---|---|
ScheduleExpression | EventBridge Schedule Expression | cron(30 10 2 * ? *) |
Schedule for running the lambda |
AdminEmail | Any email address | [email protected] |
Send a report on unowned costs to this address |
SenderEmail | Any email address | [email protected] |
Value to use for the From email field |
SkipRecipients | Comma-delimited list of email addresses | '' |
Never send emails to recipients in this list (recipient opt-out) |
MinimumValue | Floating-point number | 1.0 |
Emails will not be sent for totals less than this amount |
SynapseDomain | Valid domain, prepended with @ |
@synapse.org |
Email domain used by Synapse |
SynapseTeamId | Synapse Team Id (numeric string) | 273957 |
Only send emails to synapse users if they are a member of this Team |
RestrictRecipients | True or False |
False |
If True only send emails to recipients listed in ApprovedRecipients |
ApprovedRecipients | Comma-delimited list of email addresses | '' |
If RestrictRecpipients is True , then only send emails to recipients in this list |
CopyRecipients | Comma-delimited list of email addresses | '' |
CC this list of recipients on all emails |
EventBridge schedule expression describing how often to run the lambda. By default it runs at 10:30am UTC on the 2nd of each month.
An administrative report summarizing unowned costs per account will be sent to this address.
This email address will appear is the From
field, and must be
verified
before emails will successfully send.
A skip list of email addresses. Any recipient listed here will be skipped, useful for recipients who want to opt-out of notifications.
Don't send an email if the reported monthly total is less than this amount, by default $1.
The email domain used by Synapse. If an email recipient is at this domain, the recipient must also be a member of the listed Synapse team.
Only send notifications to Synapse users if they are also a member of this team. This only affects email addresses matching SynapseDomain.
Boolean value to toggle enforcing an ApprovedRecipients
allow list of email
recipients. Useful for testing.
An allow list of recipient addresses, any recipient not listed here will be
skipped, only respected when RestrictRecipients
is True
. Does not override
SkipRecipients
. Useful for testing.
A list of email addresses to CC on all emails.
The lambda is configured to run on a schedule, by default at 10:30am UTC on the 2nd of each month. Ad-hoc runs for testing can be triggered with an empty test event from the Lambda console page
Contributions are welcome.
Install the following applications:
Check in .travis.yml to see how they are installed for this repo.
Run pipenv install --dev
to install both production and development
requirements, and pipenv shell
to activate the virtual environment. For more
information see the pipenv docs.
After activating the virtual environment, run pre-commit install
to install
the pre-commit git hook.
First, make any needed updates to the base requirements in Pipfile
, then use
pipenv
to regenerate both Pipfile.lock
and requirements.txt
.
$ pipenv update --dev
We use pipenv
to control versions in testing, but sam
relies on
requirements.txt
directly for building the lambda artifact, so we dynamically
generate requirements.txt
from Pipfile.lock
before building the artifact.
The file must be created in the CodeUri
directory specified in
template.yaml
.
$ pipenv requirements > requirements.txt
Additionally, pre-commit
manages its own requirements.
$ pre-commit autoupdate
Use a Lambda-like docker container to build the Lambda artifact
$ sam build --use-container
Tests are defined in the tests
folder in this project, and dependencies are
managed with pipenv
. Install the development dependencies and run the tests
using coverage
.
$ pipenv run coverage run -m pytest tests/ -svv
Automated testing will upload coverage results to Coveralls.
Running integration tests requires docker
$ sam local invoke HelloWorldFunction --event events/event.json
Deployments are sent to the
Sage cloudformation repository
which requires permissions to upload to Sage
bootstrap-awss3cloudformationbucket-19qromfd235z9
and
essentials-awss3lambdaartifactsbucket-x29ftznj6pqw
buckets.
sam package --template-file .aws-sam/build/template.yaml \
--s3-bucket essentials-awss3lambdaartifactsbucket-x29ftznj6pqw \
--output-template-file .aws-sam/build/lambda-template.yaml
aws s3 cp .aws-sam/build/lambda-template.yaml s3://bootstrap-awss3cloudformationbucket-19qromfd235z9/lambda-template/master/
Publishing the lambda makes it available in your AWS account. It will be accessible in the serverless application repository.
sam publish --template .aws-sam/build/lambda-template.yaml
Making the lambda publicly accessible makes it available in the global AWS serverless application repository
aws serverlessrepo put-application-policy \
--application-id <lambda ARN> \
--statements Principals=*,Actions=Deploy
When using AWS Organizations, the lambda should be deployed once in the master account to aggregate all costs from the member accounts. Otherwise it must be deployed into each separate account, resulting in a separate email for each account total.
Create the following sceptre file config/prod/lambda-template.yaml
template:
type: http
url: "https://PUBLISH_BUCKET.s3.amazonaws.com/lambda-template/VERSION/lambda-template.yaml"
stack_name: "lambda-template"
stack_tags:
OwnerEmail: "[email protected]"
Install the lambda using sceptre:
sceptre --var "profile=my-profile" --var "region=us-east-1" launch prod/lambda-template.yaml
Steps to deploy from AWS console.
- Login to AWS
- Access the serverless application repository -> Available Applications
- Select application to install
- Enter Application settings
- Click Deploy
We have setup our CI to automate a releases. To kick off the process just create a tag (i.e 0.0.1) and push to the repo. The tag must be the same number as the current version in template.yaml. Our CI will do the work of deploying and publishing the lambda.
Some manual verification and testing must be performed with the initial deploy.
In order for SES to send emails, the sender address must be verified prior to the first run of the lambda.
If the AWS Account is in the SES Sandbox, then recipient addresses will also need to be verified prior to the first run of the lambda.
Once the needed addresses have been verified, the lambda should be tested with a
canary run, restricting output to a list of approved canary users by using the
RestrictRecipients
and ApprovedRecipients
parameters.
template:
type: http
url: "https://PUBLISH_BUCKET.s3.amazonaws.com/lambda-template/VERSION/lambda-template.yaml"
stack_name: "lambda-template"
stack_tags:
OwnerEmail: "[email protected]"
parameters:
RestrictRecipients: "True"
ApprovedRecipients: "[email protected],[email protected]"
Once the sender email address has been verified and a canary run has succeeded, the AWS account must be move out of the SES Sandbox.
After moving the AWS account out of the SES Sandbox, redeploy the lambda without recipient restrictions and with any other needed parameters.
template:
type: http
url: "https://PUBLISH_BUCKET.s3.amazonaws.com/lambda-template/VERSION/lambda-template.yaml"
stack_name: "lambda-template"
stack_tags:
OwnerEmail: "[email protected]"
parameters:
RestrictRecipients: "False"
CopyRecipients: "[email protected]"