Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Commit

Permalink
[enable_cert_updates]
Browse files Browse the repository at this point in the history
    Created a fab task to update certificates on a stack. Checks are carried out to see if the current local and remote certificates are the same,
    if not the certificates are uploaded and and load balancers with certificates in the stack will be updated
    fab_tasks:
        - Create a fab task update_certs to update the ssl certificates from the config
        - Small delay between updating certificates on instances and load balancer to avoid setting the load balancer cert when ARN is available but the
            certificate is not properly registered
    iam:
        - Added getting an arn from a certificate name to the IAM class.
        - Simplify getting an arn for certs using boto get_server_certificate
        - Handle exceptions when trying to delete/upload a certificate
    elb:
        - Create an ELB class to handle interaction with the stacks load balancers.
        - Throw an exception if we try to set certs on elbs when none are defined in the config
    cloudformation:
        - Added utility method to get a list of load balancers for the stack
    test_iam:
        - Added test cases to cover noew iam things
  • Loading branch information
Niall Creech committed Apr 17, 2015
1 parent e4e41a2 commit 54f1243
Show file tree
Hide file tree
Showing 6 changed files with 722 additions and 13 deletions.
20 changes: 20 additions & 0 deletions bootstrap_cfn/cloudformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,23 @@ def stack_missing(self, stack_name):

def wait_for_stack_missing(self, stack_id, timeout=3600, interval=30):
return utils.timeout(timeout, interval)(self.stack_missing)(stack_id)

def get_stack_load_balancers(self, stack_name_or_id):
"""
Collect up the load balancer set of stack resources
Args:
stack_name_or_id (string): Name or id used to identify the stack
Returns:
load_balancers: Set of stack resources containing only
load balancers for this stack
"""
# get the stack
load_balancers = []
stack = self.conn_cfn.describe_stacks(stack_name_or_id)
if stack:
fn = lambda x: x.resource_type == 'AWS::ElasticLoadBalancing::LoadBalancer'
# get the load balancers group
load_balancers = filter(fn, stack[0].list_resources())
return load_balancers
77 changes: 77 additions & 0 deletions bootstrap_cfn/elb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import sys
import logging
import boto.ec2.elb
from bootstrap_cfn import cloudformation
from bootstrap_cfn import iam
from bootstrap_cfn import utils
from bootstrap_cfn.errors import CloudResourceNotFoundError


class ELB:

cfn = None
iam = None
aws_region_name = None
aws_profile_name = None

def __init__(self, aws_profile_name, aws_region_name='eu-west-1'):
self.aws_profile_name = aws_profile_name
self.aws_region_name = aws_region_name

self.conn_elb = utils.connect_to_aws(boto.ec2.elb, self)

self.iam = iam.IAM(aws_profile_name, aws_region_name)
self.cfn = cloudformation.Cloudformation(
aws_profile_name, aws_region_name
)

def set_ssl_certificates(self, ssl_config, stack_name):
"""
Look for SSL listeners on all the load balancers connected to
this stack, then set update the certificate to that of the config
Args:
ssl_config (dictionary): Certification names to corresponding data
stack_name (string): Name of the stack
Raises:
CloudResourceNotFoundError: Raised when the load balancer key in the cloud
config is not found
"""
for cert_name in ssl_config.keys():
# Get the cert id and also its arn
cert_id = "{0}-{1}".format(cert_name, stack_name)
cert_arn = self.iam.get_arn_for_cert(cert_id)

# Get all stack load balancers
load_balancer_resources = self.cfn.get_stack_load_balancers(stack_name)
found_load_balancer_names = [lb.physical_resource_id for lb in load_balancer_resources]
# Use load balancer names to filter gettingload balancer details
if len(found_load_balancer_names) > 0:
load_balancers = self.conn_elb.get_all_load_balancers(load_balancer_names=found_load_balancer_names)

# Look for https listeners on load balancers and update the cert
# using the arn
if len(load_balancers) > 0:
for load_balancer in load_balancers:
for listener in load_balancer.listeners:
# Get protocol, if https, update cert
# in_port = listener[0]
out_port = listener[1]
protocol = listener[2]
# If the protocol is HTTPS then set the cert on the listener
if protocol == "HTTPS":
logging.info("ELB::set_ssl_certificates: "
"Found HTTPS protocol on '%s', "
"updating SSL certificate with '%s'"
% (load_balancer.name, cert_arn))
self.conn_elb.set_lb_listener_SSL_certificate(load_balancer.name,
out_port,
cert_arn
)
else:
# Throw key error. There being no load balancers to update is not
# necessarily a problem but since the caller expected there to be let
# it handle this situation
raise CloudResourceNotFoundError("ELB::set_ssl_certificates: "
"No load balancers found in stack,")
3 changes: 3 additions & 0 deletions bootstrap_cfn/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ class SaltStateError(BootstrapCfnError):

class SaltParserError(BootstrapCfnError):
pass

class CloudResourceNotFoundError(BootstrapCfnError):
pass
43 changes: 42 additions & 1 deletion bootstrap_cfn/fab_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import os
from StringIO import StringIO
import sys
import time
import logging
import random
import yaml

Expand All @@ -14,7 +16,7 @@
from bootstrap_cfn.cloudformation import Cloudformation
from bootstrap_cfn.ec2 import EC2
from bootstrap_cfn.iam import IAM

from bootstrap_cfn.elb import ELB


# GLOBAL VARIABLES
Expand Down Expand Up @@ -312,3 +314,42 @@ def rsync():
'cloudformation.sls'),
local_path=cf_sls,
use_sudo=True)


@task
def update_certs(force=False):
"""
Update the ssl certificates with those in the config file.
Also handle settings the certificates on ELB's
"""
if force:
logging.info("Forcing certificate updates is enabled...")

stack_name = get_stack_name()
cfn_config = get_config()
# Upload any SSL certificates to our EC2 instances
updated_count = False
if 'ssl' in cfn_config.data:
logging.info("Reloading SSL certificates...")
iam = get_connection(IAM)
updated_count = iam.update_ssl_certificates(cfn_config.ssl(),
stack_name,
force)
else:
logging.error("No ssl section found in cloud config file, aborting...")
sys.exit(1)

# Arbitrary wait to allow SSL upload to register with AWS
# Otherwise, we can get an ARN for the load balancer certificates
# without it being ready to assign
time.sleep(3)

# Set the certificates on ELB's if we have any
if updated_count > 0:
if 'elb' in cfn_config.data:
logging.info("Setting load balancer certificates...")
elb = get_connection(ELB)
elb.set_ssl_certificates(cfn_config.ssl(), stack_name)
else:
logging.error("No certificates updated so skipping "
"ELB certificate update...")

0 comments on commit 54f1243

Please sign in to comment.