From d1c03e5e8c5064014d6070190e85ae15a821885d Mon Sep 17 00:00:00 2001 From: Ryan Ahearn Date: Tue, 31 Jan 2023 17:27:17 -0500 Subject: [PATCH] Get SES config from VCAP_SERVICES --- app/__init__.py | 3 +- app/clients/email/aws_ses.py | 12 +++++-- app/clients/email/aws_ses_stub.py | 2 +- app/cloudfoundry_config.py | 42 +++++++++++++++++++++++++ app/config.py | 4 +-- app/notifications/sns_cert_validator.py | 3 +- manifest.yml | 2 +- 7 files changed, 57 insertions(+), 11 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 456194694..38df2f5f7 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -95,9 +95,8 @@ def create_app(application): logging.init_app(application) aws_sns_client.init_app(application, statsd_client=statsd_client) - aws_ses_client.init_app(application.config['AWS_REGION'], statsd_client=statsd_client) + aws_ses_client.init_app(statsd_client=statsd_client) aws_ses_stub_client.init_app( - application.config['AWS_REGION'], statsd_client=statsd_client, stub_url=application.config['SES_STUB_URL'] ) diff --git a/app/clients/email/aws_ses.py b/app/clients/email/aws_ses.py index 1f8b2f75c..59d2243ac 100644 --- a/app/clients/email/aws_ses.py +++ b/app/clients/email/aws_ses.py @@ -1,7 +1,7 @@ from time import monotonic -import boto3 import botocore +from boto3 import client from flask import current_app from app.clients import STATISTICS_DELIVERED, STATISTICS_FAILURE @@ -10,6 +10,7 @@ from app.clients.email import ( EmailClientException, EmailClientNonRetryableException, ) +from app.cloudfoundry_config import cloud_config ses_response_map = { 'Permanent': { @@ -56,8 +57,13 @@ class AwsSesClient(EmailClient): Amazon SES email client. ''' - def init_app(self, region, statsd_client, *args, **kwargs): - self._client = boto3.client('ses', region_name=region) + def init_app(self, statsd_client, *args, **kwargs): + self._client = client( + 'ses', + region_name=cloud_config.ses_region, + aws_access_key_id=cloud_config.ses_access_key, + aws_secret_access_key=cloud_config.ses_secret_key + ) super(AwsSesClient, self).__init__(*args, **kwargs) self.statsd_client = statsd_client diff --git a/app/clients/email/aws_ses_stub.py b/app/clients/email/aws_ses_stub.py index bce9d3e9a..ef5fc8c13 100644 --- a/app/clients/email/aws_ses_stub.py +++ b/app/clients/email/aws_ses_stub.py @@ -12,7 +12,7 @@ class AwsSesStubClientException(EmailClientException): class AwsSesStubClient(EmailClient): - def init_app(self, region, statsd_client, stub_url): + def init_app(self, statsd_client, stub_url): self.statsd_client = statsd_client self.url = stub_url diff --git a/app/cloudfoundry_config.py b/app/cloudfoundry_config.py index aa7b3b543..a23ee260c 100644 --- a/app/cloudfoundry_config.py +++ b/app/cloudfoundry_config.py @@ -31,5 +31,47 @@ class CloudfoundryConfig: def s3_credentials(self, service_name): return self.s3_buckets.get(service_name) or self._empty_bucket_credentials + @property + def ses_email_domain(self): + try: + return self._ses_credentials('domain_arn').split('/')[-1] + except KeyError: + return getenv('NOTIFY_EMAIL_DOMAIN', 'notify.sandbox.10x.gsa.gov') + + @property + def ses_region(self): + try: + return self._ses_credentials('region') + except KeyError: + return getenv('AWS_REGION') + + @property + def ses_access_key(self): + try: + return self._ses_credentials('smtp_user') + except KeyError: + return getenv('AWS_ACCESS_KEY_ID') + + @property + def ses_secret_key(self): + try: + return self._ses_credentials('secret_access_key') + except KeyError: + return getenv('AWS_SECRET_ACCESS_KEY') + + @property + def sns_topic_arns(self): + try: + return [ + self._ses_credentials('bounce_topic_arn'), + self._ses_credentials('complaint_topic_arn'), + self._ses_credentials('delivery_topic_arn') + ] + except KeyError: + return [] + + def _ses_credentials(self, key): + return self.parsed_services['datagov-smtp'][0]['credentials'][key] + cloud_config = CloudfoundryConfig() diff --git a/app/config.py b/app/config.py index 10d4220c8..b3c0519ba 100644 --- a/app/config.py +++ b/app/config.py @@ -108,11 +108,11 @@ class Config(object): AWS_US_TOLL_FREE_NUMBER = getenv("AWS_US_TOLL_FREE_NUMBER") # Whether to ignore POSTs from SNS for replies to SMS we sent RECEIVE_INBOUND_SMS = False - NOTIFY_EMAIL_DOMAIN = getenv('NOTIFY_EMAIL_DOMAIN', 'notify.sandbox.10x.gsa.gov') + NOTIFY_EMAIL_DOMAIN = cloud_config.ses_email_domain SES_STUB_URL = None # TODO: set to a URL in env and remove this to use a stubbed SES service # AWS SNS topics for delivery receipts VALIDATE_SNS_TOPICS = True - VALID_SNS_TOPICS = ['notify_test_bounce', 'notify_test_success', 'notify_test_complaint', 'notify_test_sms_inbound'] + VALID_SNS_TOPICS = cloud_config.sns_topic_arns # these should always add up to 100% SMS_PROVIDER_RESTING_POINTS = { diff --git a/app/notifications/sns_cert_validator.py b/app/notifications/sns_cert_validator.py index 1fbddd811..1b3f7ea3d 100644 --- a/app/notifications/sns_cert_validator.py +++ b/app/notifications/sns_cert_validator.py @@ -39,8 +39,7 @@ def get_certificate(url): def validate_arn(sns_payload): if VALIDATE_SNS_TOPICS: arn = sns_payload.get('TopicArn') - topic_name = arn.split(':')[5] - if topic_name not in VALID_SNS_TOPICS: + if arn not in VALID_SNS_TOPICS: raise ValidationError("Invalid Topic Name") diff --git a/manifest.yml b/manifest.yml index e8d19a5cb..abf8dde6f 100644 --- a/manifest.yml +++ b/manifest.yml @@ -15,7 +15,7 @@ applications: - notify-api-contact-list-bucket-((env)) - name: notify-api-ses-((env)) parameters: - notification_webhook: "" + notification_webhook: "https://((public_api_route))/notifications/email/ses" processes: - type: web