Skip to content

Commit

Permalink
Route SNS notifications through a Lambda function (#5246)
Browse files Browse the repository at this point in the history
  • Loading branch information
achave11-ucsc committed Aug 29, 2023
1 parent 7fb38a6 commit d37cdec
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 4 deletions.
19 changes: 19 additions & 0 deletions lambdas/indexer/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
from azul.indexer.log_forwarding_controller import (
LogForwardingController,
)
from azul.indexer.notify_controller import (
NotifyController,
)
from azul.logging import (
configure_app_logging,
)
Expand Down Expand Up @@ -74,6 +77,10 @@ class IndexerApp(AzulChaliceApp, SignatureHelper):
def health_controller(self):
return self._controller(HealthController, lambda_name='indexer')

@cached_property
def notify_controller(self):
return self._controller(NotifyController)

@cached_property
def index_controller(self) -> IndexController:
return self._controller(IndexController)
Expand All @@ -97,6 +104,13 @@ def log_forwarder(self, prefix: str):
else:
return lambda func: func

@property
def monitoring(self):
if config.enable_monitoring:
return self.on_sns_message(topic=config.qualified_resource_name('monitoring'))
else:
return lambda func: func

def _authenticate(self) -> Optional[HMACAuthentication]:
return self.auth_from_request(self.current_request)

Expand Down Expand Up @@ -291,3 +305,8 @@ def forward_alb_logs(event: chalice.app.S3Event):
@app.log_forwarder(config.s3_access_log_path_prefix(deployment=None))
def forward_s3_logs(event: chalice.app.S3Event):
app.log_controller.forward_s3_access_logs(event)


@app.monitoring
def notify(event: chalice.app.SNSEvent):
app.notify_controller.digest(event)
4 changes: 4 additions & 0 deletions src/azul/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ def securityhub(self):
def sns(self):
return self.client('sns')

@property
def ses(self):
return self.client('ses')

@property
def sts(self):
return self.client('sts')
Expand Down
21 changes: 21 additions & 0 deletions src/azul/indexer/notify_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import chalice.app

from azul import (
cached_property,
)
from azul.chalice import (
AppController,
)
from azul.indexer.notify_service import (
AzulEmailNotificationService,
)


class NotifyController(AppController):

@cached_property
def email(self):
return AzulEmailNotificationService()

def digest(self, event: chalice.app.SNSEvent) -> None:
self.email.notify_group(subject=event.subject, body=event.message)
26 changes: 26 additions & 0 deletions src/azul/indexer/notify_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from azul import config, JSON
from azul.deployment import aws


class AzulEmailNotificationService:

def notify_group(self, subject: str, body: str) -> None:
aws.ses.send_email(
Source=f'notify@{config.indexer_endpoint.host}',
Destination={
'ToAddresses': [config.monitoring_email]
},
Message=self._format_message(subject, body)
)

def _format_message(self, subject: str, body: str) -> JSON:
return {
'Subject': {
'Data': subject
},
'Body': {
'Text': {
'Data': body
}
}
}
61 changes: 57 additions & 4 deletions terraform/api_gateway.tf.json.template.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,52 @@ def for_domain(cls, domain):
'sampled_requests_enabled': True,
}
}
}
},
**(
(
{
'aws_route53_record': {
'notify_amazonses_record': {
'zone_id': '${data.aws_route53_zone.dev_singlecell_gi_ucsc_edu.id}',
'name': f'_amazonses.{config.api_lambda_domain("indexer")}',
'type': 'TXT',
'ttl': '600',
'records': [
'${aws_ses_domain_identity.notify.verification_token}'
]
}
},
'aws_ses_domain_identity': {
'notify': {
'domain': config.api_lambda_domain('indexer')
}
},
'aws_ses_identity_policy': {
'notify': {
'identity': '${aws_ses_domain_identity.notify.arn}',
'name': config.qualified_resource_name('notify'),
'policy': json.dumps({
"Version": "2012-10-17",
"Statement": [
{
'Effect': 'Allow',
'Principal': {
'AWS': f'arn:aws:sts::{aws.account}:assumed-role/{config.indexer_name}/'
+ config.indexer_function_name('notify')
},
'Action': [
'ses:SendEmail',
'ses:SendRawEmail'
],
'Resource': '${aws_ses_domain_identity.notify.arn}',
}
]
})
}
}
}
) if config.enable_monitoring else {}
)
},
*([
{
Expand All @@ -327,13 +372,21 @@ def for_domain(cls, domain):
'maximum_retry_attempts': 0
}
for function_name in (
'forward_alb_logs',
'forward_s3_logs',
*(
('forward_alb_logs', 'forward_s3_logs')
if config.enable_log_forwarding else
()
),
*(
('notify',)
if config.enable_monitoring else
()
)
)
}
}
]
if config.enable_log_forwarding else
if config.enable_log_forwarding or config.enable_monitoring else
[]),
*(
{
Expand Down
6 changes: 6 additions & 0 deletions terraform/shared/shared.tf.json.template.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ def paren(s: str) -> str:
vpc.default_vpc_name: {
'default': True
}
},
'aws_route53_zone': {
'gitlab': {
'name': config.domain_name + '.',
'private_zone': False
}
}
},
'resource': {
Expand Down

0 comments on commit d37cdec

Please sign in to comment.