Skip to content

Commit

Permalink
- Fixed elasticache security group CFN Parameter logical name
Browse files Browse the repository at this point in the history
- Added CodeBuild support to EventsRule
- Automated up VPC Peering between netenvs
  • Loading branch information
gitwater committed Jan 26, 2022
1 parent 27e5b76 commit 9946ec6
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/paco/cftemplates/elasticache.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def __init__(self, stack, paco_ctx):
vpc_sg_list = []
for sg_ref in elasticache_config.security_groups:
ref = Reference(sg_ref)
sg_param_name = 'SecurityGroupId'+ref.parts[-2]+ref.parts[-1]
sg_param_name = self.create_cfn_logical_id('SecurityGroupId'+ref.parts[-2]+ref.parts[-1])
sg_param = self.create_cfn_parameter(
name=sg_param_name,
param_type='String',
Expand Down
31 changes: 26 additions & 5 deletions src/paco/cftemplates/eventsrule.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
"""

from paco.cftemplates.cftemplates import StackTemplate
from paco.models import vocabulary
from paco.models import vocabulary, schemas
from paco.models.references import get_model_obj_from_ref, Reference
from paco.utils import hash_smaller
from awacs.aws import Allow, Statement, Policy, Principal
from enum import Enum
from io import StringIO
import awacs.awslambda
import awacs.codebuild
import awacs.sts
import base64
import os
Expand Down Expand Up @@ -41,6 +43,9 @@ def __init__(
# Init a Troposphere template
self.init_template('CloudWatch EventsRule')

if eventsrule.is_enabled() == False:
return

# Parameters
schedule_expression_param = self.create_cfn_parameter(
param_type = 'String',
Expand All @@ -59,13 +64,14 @@ def __init__(
targets = []
self.target_params = {}
for index in range(0, len(eventsrule.targets)):
target = eventsrule.targets[index]
# Target Parameters
target_name = 'Target{}'.format(index)
self.target_params[target_name + 'Arn'] = self.create_cfn_parameter(
param_type='String',
name=target_name + 'Arn',
description=target_name + ' Arn for the Events Rule.',
value=eventsrule.targets[index].target + '.arn',
value=target.target + '.arn',
)
self.target_params[target_name] = self.create_cfn_parameter(
param_type='String',
Expand All @@ -77,8 +83,8 @@ def __init__(
'Arn': troposphere.Ref(self.target_params[target_name + 'Arn']),
'Id': troposphere.Ref(self.target_params[target_name]),
}
if eventsrule.targets[index].input_json != None:
cfn_export_dict['Input'] = eventsrule.targets[index].input_json
if target.input_json != None:
cfn_export_dict['Input'] = target.input_json

# Events Rule Targets
targets.append(
Expand All @@ -88,6 +94,20 @@ def __init__(
)
)

# Lambda Policy Actions
target_ref = Reference(target.target)
if target_ref.parts[-1] == 'project' and target_ref.parts[-3] == 'build':
codebuild_target_ref = f'paco.ref {".".join(target_ref.parts[:-1])}'
target_model_obj = get_model_obj_from_ref(codebuild_target_ref, self.paco_ctx.project)
else:
target_model_obj = get_model_obj_from_ref(target.target, self.paco_ctx.project)

if schemas.IDeploymentPipelineBuildCodeBuild.providedBy(target_model_obj):
target_policy_actions = [awacs.codebuild.StartBuild]
elif schemas.ILambda.providedBy(target_model_obj):
target_policy_actions = [awacs.awslambda.InvokeFunction]


# IAM Role Resources to allow Event to invoke Target
target_invocation_role_resource = troposphere.iam.Role(
'TargetInvocationRole',
Expand All @@ -109,7 +129,7 @@ def __init__(
Statement=[
Statement(
Effect=Allow,
Action=[awacs.awslambda.InvokeFunction],
Action=target_policy_actions,
Resource=[troposphere.Ref(self.target_params[target_name + 'Arn'])],
)
]
Expand All @@ -134,6 +154,7 @@ def __init__(
Description=troposphere.Ref(description_param),
ScheduleExpression=troposphere.Ref(schedule_expression_param),
Targets=targets,
RoleArn=troposphere.Ref(target_invocation_role_resource),
State=enabled_state
)
self.template.add_resource(event_rule_resource)
Expand Down
6 changes: 6 additions & 0 deletions src/paco/cftemplates/lb.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ def init_lb(self, aws_name, template_title):
cfn_export_dict['TargetGroupAttributes'] = [
{'Key': 'deregistration_delay.timeout_seconds', 'Value': str(target_group.connection_drain_timeout) }
]
# TODO: Preserve Client IP
# if self.lb_config.type == 'LBNetwork':
# cfn_export_dict['TargetGroupAttributes'].append({
# 'Key': 'preserve_client_ip.enabled', 'Value': 'false'
# })

cfn_export_dict['VpcId'] = troposphere.Ref(vpc_param)
if target_group.target_type != 'instance':
cfn_export_dict['TargetType'] = target_group.target_type
Expand Down
50 changes: 32 additions & 18 deletions src/paco/cftemplates/vpc_peering.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from paco.cftemplates.cftemplates import StackTemplate
from paco.core.exception import PacoException
from paco.models.locations import get_parent_by_interface
from paco.models import schemas, references
from paco.models.references import Reference
import troposphere
import troposphere.ec2
import troposphere.route53
Expand All @@ -12,10 +14,10 @@ def __init__(
stack,
paco_ctx,
):
vpc_config = stack.resource
network_config = get_parent_by_interface(vpc_config, schemas.INetwork)
env_name = get_parent_by_interface(vpc_config, schemas.IEnvironment).name
netenv_name = get_parent_by_interface(vpc_config, schemas.INetworkEnvironment).name
peering_config = stack.resource
network_config = get_parent_by_interface(peering_config, schemas.INetwork)
env_name = get_parent_by_interface(peering_config, schemas.IEnvironment).name
netenv_name = get_parent_by_interface(peering_config, schemas.INetworkEnvironment).name
super().__init__(
stack,
paco_ctx,
Expand All @@ -33,8 +35,8 @@ def __init__(

# Peer
any_peering_enabled = False
for peer in vpc_config.peering.keys():
peer_config = vpc_config.peering[peer]
for peer in peering_config.keys():
peer_config = peering_config[peer]
if peer_config.is_enabled() and peer_config.peer_type == 'requester':
any_peering_enabled = True
else:
Expand All @@ -55,22 +57,34 @@ def __init__(
self.template.add_resource(vpc_peering_connection_res)
# Routes
for route in peer_config.routing:
for az in range(0, network_config.availability_zones):
az_str = str(az+1)
resource_name_suffix = peer.title() + 'AZ' + az_str
for peer_az in range(0, network_config.availability_zones):
peer_az_str = str(peer_az+1)
resource_name_suffix = peer.title() + 'AZ' + peer_az_str
route_table_param = self.create_cfn_parameter(
name='PeerRouteTableId' + resource_name_suffix,
param_type='String',
description='The route table ID for AZ {}.'.format(az_str),
value='{}.az{}.route_table.id'.format(route.segment, az_str),
description='The route table ID for AZ {}.'.format(peer_az_str),
value='{}.az{}.route_table.id'.format(route.local_segment, peer_az_str),
)
peer_route_res = troposphere.ec2.Route(
'PeeringRoute' + resource_name_suffix,
DestinationCidrBlock = route.cidr,
VpcPeeringConnectionId = troposphere.Ref(vpc_peering_connection_res),
RouteTableId = troposphere.Ref(route_table_param)
)
self.template.add_resource(peer_route_res)

remote_availability_zones = self.paco_ctx.get_ref(peer_config.network_environment+'.network.availability_zones')
for route_az in range(0, remote_availability_zones):
route_az_str = str(route_az+1)
if route.remote_segment != None:
route_cidr = self.paco_ctx.get_ref(route.remote_segment+f'.az{route_az_str}_cidr')
elif route.cidr != None:
raise PacoException("cidr is not supported yet, please use remote_segment.")
else:
raise PacoException("remote_segment must be specified in VPC Peer.")

peer_route_name = self.create_cfn_logical_id_join(['PeeringRoute', resource_name_suffix, f'RemoteAZ{route_az_str}'], camel_case=True)
peer_route_res = troposphere.ec2.Route(
peer_route_name,
DestinationCidrBlock = route_cidr,
VpcPeeringConnectionId = troposphere.Ref(vpc_peering_connection_res),
RouteTableId = troposphere.Ref(route_table_param)
)
self.template.add_resource(peer_route_res)

self.set_enabled(any_peering_enabled)

Expand Down
7 changes: 3 additions & 4 deletions src/paco/stack_grps/grp_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def init(self):
self.gen_vpc_peering_accepter_role(peer_config, vpc_config, accepter_vpc_id, requester_account_id)
self.peering_stack = self.add_new_stack(
self.region,
vpc_config,
vpc_config.peering,
paco.cftemplates.VPCPeering,
stack_tags=StackTags(self.stack_tags),
)
Expand Down Expand Up @@ -233,7 +233,7 @@ def gen_vpc_peering_accepter_role(self, peer_config, vpc_config, accepter_vpc_id
'ec2:AccepterVpc': { "Fn::Sub" : [ f'arn:aws:ec2:{accepter_region}:{accepter_account_id}:vpc/${{VpcId}}', { "VpcId": {"Ref" : "VpcId"} } ] }
}
}
role_config = iam.Role('accepter_role', peer_config)
role_config = iam.Role(f'Peering-{peer_config.name}-accepter-role', peer_config)
role_config.apply_config(role_config_dict)
role_config.enabled = True
role_config.role_name = 'Peer-Accepter'
Expand All @@ -247,11 +247,10 @@ def gen_vpc_peering_accepter_role(self, peer_config, vpc_config, accepter_vpc_id
'type': 'String',
'description': 'Acceptor VPC ID'
}]

iam_ctl.add_role(
account_ctx=self.account_ctx,
region=self.region,
resource=peer_config,
resource=vpc_config,
role=role_config,
iam_role_id=f'VPC-Peer-{peer_config.name}-Accepter',
stack_group=self,
Expand Down

0 comments on commit 9946ec6

Please sign in to comment.