Skip to content

Commit

Permalink
Merge pull request #282 from zalando-stups/acm-region
Browse files Browse the repository at this point in the history
Provide region to ACM
  • Loading branch information
hjacobs committed Jul 27, 2016
2 parents 56b109c + 5a0fabd commit 9f0d2b7
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 14 deletions.
19 changes: 13 additions & 6 deletions senza/components/elastic_load_balancer.py
Expand Up @@ -2,6 +2,7 @@
from clickclick import fatal_error

from senza.aws import resolve_security_groups
from ..cli import AccountArguments, TemplateArguments
from ..manaus import ClientError
from ..manaus.iam import IAM, IAMServerCertificate
from ..manaus.acm import ACM, ACMCertificate
Expand All @@ -23,13 +24,14 @@ def get_load_balancer_name(stack_name: str, stack_version: str):
return '{}-{}'.format(stack_name[:l], stack_version)


def get_listeners(subdomain, main_zone, configuration):
def get_listeners(subdomain, main_zone, configuration,
account_info: AccountArguments):
ssl_cert = configuration.get('SSLCertificateId')

if ACMCertificate.arn_is_acm_certificate(ssl_cert):
# check if certificate really exists
try:
ACMCertificate.get_by_arn(ssl_cert)
ACMCertificate.get_by_arn(account_info.Region, ssl_cert)
except ClientError as e:
error_msg = e.response['Error']['Message']
fatal_error(error_msg)
Expand All @@ -44,7 +46,8 @@ def get_listeners(subdomain, main_zone, configuration):
iam_pattern = main_zone.lower().rstrip('.').replace('.', '-')
name = '{sub}.{zone}'.format(sub=subdomain,
zone=main_zone.rstrip('.'))
acm_certificates = sorted(ACM.get_certificates(domain_name=name),
acm = ACM(account_info.Region)
acm_certificates = sorted(acm.get_certificates(domain_name=name),
reverse=True)
else:
iam_pattern = ''
Expand Down Expand Up @@ -79,9 +82,13 @@ def get_listeners(subdomain, main_zone, configuration):
]


def component_elastic_load_balancer(definition, configuration, args, info, force, account_info):
def component_elastic_load_balancer(definition,
configuration: dict,
args: TemplateArguments,
info: dict,
force,
account_info: AccountArguments):
lb_name = configuration["Name"]

# domains pointing to the load balancer
subdomain = ''
main_zone = None
Expand All @@ -107,7 +114,7 @@ def component_elastic_load_balancer(definition, configuration, args, info, force
subdomain = domain['Subdomain']
main_zone = domain['Zone'] # type: str

listeners = configuration.get('Listeners') or get_listeners(subdomain, main_zone, configuration)
listeners = configuration.get('Listeners') or get_listeners(subdomain, main_zone, configuration, account_info)

health_check_protocol = "HTTP"
allowed_health_check_protocols = ("HTTP", "TCP", "UDP", "SSL")
Expand Down
17 changes: 11 additions & 6 deletions senza/manaus/acm.py
Expand Up @@ -101,11 +101,11 @@ def from_boto_dict(cls,
revoked_at, revocation_reason)

@classmethod
def get_by_arn(cls, arn: str) -> "ACMCertificate":
def get_by_arn(cls, region: str, arn: str) -> "ACMCertificate":
"""
Gets a ACMCertificate based on ARN alone
"""
client = boto3.client('acm')
client = boto3.client('acm', region)
certificate = client.describe_certificate(CertificateArn=arn)['Certificate']
return cls.from_boto_dict(certificate)

Expand Down Expand Up @@ -156,21 +156,26 @@ class ACM:
See http://boto3.readthedocs.io/en/latest/reference/services/acm.html
"""

@staticmethod
def get_certificates(valid_only: bool=True,
def __init__(self, region=str):
self.region = region

def get_certificates(self,
*,
valid_only: bool=True,
domain_name: Optional[str]=None) -> Iterator[ACMCertificate]:
"""
Gets certificates from ACM. By default it returns all valid certificates
:param region: AWS region
:param valid_only: Return only valid certificates
:param domain_name: Return only certificates that match the domain
"""
# TODO implement pagination
client = boto3.client('acm')
client = boto3.client('acm', self.region)
certificates = client.list_certificates()['CertificateSummaryList']
for summary in certificates:
arn = summary['CertificateArn']
certificate = ACMCertificate.get_by_arn(arn)
certificate = ACMCertificate.get_by_arn(self.region, arn)
if valid_only and not certificate.is_valid():
pass
elif domain_name is not None and not certificate.matches(domain_name):
Expand Down
5 changes: 3 additions & 2 deletions tests/test_manaus/test_acm.py
Expand Up @@ -148,7 +148,8 @@ def test_certificate_get_by_arn(monkeypatch):
m_client.describe_certificate.return_value = {'Certificate': CERT1}
monkeypatch.setattr('boto3.client', m_client)

certificate1 = ACMCertificate.get_by_arn('arn:aws:acm:eu-west-1:cert')
certificate1 = ACMCertificate.get_by_arn('dummy-region',
'arn:aws:acm:eu-west-1:cert')
assert certificate1.domain_name == '*.senza.example.com'
assert certificate1.is_valid(when=datetime(2016, 4, 5, 12, 14, 14,
tzinfo=timezone.utc))
Expand Down Expand Up @@ -183,7 +184,7 @@ def test_get_certificates(monkeypatch):
tzinfo=timezone.utc)
monkeypatch.setattr('senza.manaus.acm.datetime', m_datetime)

acm = ACM()
acm = ACM('dummy-region')
certificates_default = list(acm.get_certificates())
assert len(certificates_default) == 1 # Cert2 is excluded because it's REVOKED
assert certificates_default[0].arn == 'arn:aws:acm:eu-west-1:cert1'
Expand Down

0 comments on commit 9f0d2b7

Please sign in to comment.