Beispiel #1
0
def add_service_actions(alarm, alarms_stack, target, scaling_in_policy,
                        scaling_out_policy):
    """
    Function to update the alarm properties with OKActions and AlarmActions

    :param ecs_composex.alarms.alarms_stack.Alarm alarm:
    :param ecs_composex.common.stacks.ComposeXStack alarms_stack:
    :param tuple target:
    :param scaling_in_policy:
    :param scaling_out_policy:
    """
    setattr(
        alarm,
        "Threshold",
        float(scaling_out_policy.StepScalingPolicyConfiguration.
              StepAdjustments[0].MetricIntervalLowerBound),
    )
    if not alarm.cfn_resource:
        raise AttributeError(
            f"Alarm {alarm.logical_name} has no CFN object associated")
    service_scaling_in_policy_param = Parameter(
        f"{target[0].logical_name}ScaleInPolicy", Type="String")
    service_scaling_out_policy_param = Parameter(
        f"{target[0].logical_name}ScaleOutPolicy", Type="String")
    add_parameters(
        alarms_stack.stack_template,
        [service_scaling_in_policy_param, service_scaling_out_policy_param],
    )
    add_outputs(
        target[0].template,
        [
            Output(
                f"{target[0].logical_name}ScaleInPolicy",
                Value=Ref(scaling_in_policy),
            ),
            Output(
                f"{target[0].logical_name}ScaleOutPolicy",
                Value=Ref(scaling_out_policy),
            ),
        ],
    )
    alarms_stack.Parameters.update({
        service_scaling_in_policy_param.title:
        GetAtt(
            target[0].logical_name,
            f"Outputs.{target[0].logical_name}ScaleInPolicy",
        ),
        service_scaling_out_policy_param.title:
        GetAtt(
            target[0].logical_name,
            f"Outputs.{target[0].logical_name}ScaleOutPolicy",
        ),
    })
    actions = get_alarm_actions(alarm)
    actions[0].append(Ref(service_scaling_in_policy_param))
    actions[1].append(Ref(service_scaling_out_policy_param))
Beispiel #2
0
 def generate_outputs(self):
     for (
             attribute_parameter,
             output_definition,
     ) in self.output_properties.items():
         output_name = f"{self.title}{attribute_parameter.title}"
         value = self.set_new_resource_outputs(output_definition)
         self.attributes_outputs[attribute_parameter] = {
             "Name":
             output_name,
             "Output":
             Output(output_name, Value=value),
             "ImportParameter":
             Parameter(
                 output_name,
                 return_value=attribute_parameter.return_value,
                 Type=attribute_parameter.Type,
             ),
             "ImportValue":
             GetAtt(
                 self.stack,
                 f"Outputs.{output_name}",
             ),
             "Original":
             attribute_parameter,
         }
     for attr in self.attributes_outputs.values():
         if keyisset("Output", attr):
             self.outputs.append(attr["Output"])
Beispiel #3
0
    def __init__(self, service: ComposeService, image_param: Parameter = None):
        if not keyisset("image", service.definition):
            raise KeyError(service.name, "You must define ``image``")
        self._service = service
        self._image = None

        self.image_uri = service.definition["image"]
        if not image_param:
            self._image_param = Parameter(
                f"{self.service.logical_name}ImageUrl", Type="String")
            self.image = service.definition["image"]
        else:
            self._image_param = image_param
            self.image = image_param
def set_ecs_cluster_logging_cw_access(
    settings: ComposeXSettings, policy, role_stack: ComposeXStack
) -> None:
    """
    Based on ECS Cluster settings / configurations, grant permissions to CW Log defined to log
    ECS Execute command feature

    :param ecs_composex.common.settings.ComposeXSettings settings:
    :param policy:
    :param ecs_composex.common.stacks.ComposeXStack role_stack:
    """
    if settings.ecs_cluster.log_group and settings.ecs_cluster.log_group != NoValue:
        parameter = Parameter("EcsExecuteLoggingGroup", Type="String")
        add_parameters(role_stack.stack_template, [parameter])
        if isinstance(settings.ecs_cluster.log_group, FindInMap):
            role_stack.Parameters.update(
                {parameter.title: settings.ecs_cluster.log_group}
            )
            arn_value = Sub(
                f"arn:${{{AWS_PARTITION}}}:logs:${{{AWS_REGION}}}:"
                f"${{{AWS_ACCOUNT_ID}}}:${{{parameter.title}}}:*"
            )
        else:
            role_stack.Parameters.update(
                {parameter.title: GetAtt(settings.ecs_cluster.log_group, "Arn")}
            )
            arn_value = Ref(parameter)
        policy.PolicyDocument["Statement"].append(
            {
                "Sid": "AllowDescribingAllCWLogGroupsForSSMClient",
                "Action": ["logs:DescribeLogGroups"],
                "Resource": ["*"],
                "Effect": "Allow",
            }
        )
        policy.PolicyDocument["Statement"].append(
            {
                "Action": [
                    "logs:CreateLogStream",
                    "logs:DescribeLogStreams",
                    "logs:PutLogEvents",
                ],
                "Resource": [arn_value],
                "Effect": "Allow",
            }
        )
def set_ecs_cluster_logging_s3_access(
    settings: ComposeXSettings, policy, role_stack: ComposeXStack
):
    """
    Based on ECS Cluster settings / configurations, grant permissions to put logs to S3 Bucket for logs defined to log
    ECS Execute command feature

    :param ecs_composex.common.settings.ComposeXSettings settings:
    :param policy:
    :param ecs_composex.common.stacks.ComposeXStack role_stack:
    """
    if settings.ecs_cluster.log_bucket and settings.ecs_cluster.log_bucket != NoValue:
        parameter = Parameter("EcsExecuteLoggingBucket", Type="String")
        add_parameters(role_stack.stack_template, [parameter])
        if isinstance(settings.ecs_cluster.log_bucket, FindInMap):
            role_stack.Parameters.update(
                {parameter.title: settings.ecs_cluster.log_bucket}
            )
        else:
            role_stack.Parameters.update(
                {parameter.title: Ref(settings.ecs_cluster.log_bucket.cfn_resource)}
            )
        policy.PolicyDocument["Statement"].append(
            {
                "Sid": "AllowDescribeS3Bucket",
                "Action": ["s3:GetEncryptionConfiguration"],
                "Resource": [
                    Sub(f"arn:${{{AWS_PARTITION}}}:s3:::${{{parameter.title}}}")
                ],
                "Effect": "Allow",
            }
        )
        policy.PolicyDocument["Statement"].append(
            {
                "Sid": "AllowS3BucketObjectWrite",
                "Action": ["s3:PutObject"],
                "Resource": [
                    Sub(f"arn:${{{AWS_PARTITION}}}:s3:::${{{parameter.title}}}/*")
                ],
                "Effect": "Allow",
            }
        )
    def create_vpc_mappings(self, vpc_settings):
        """
        Generates the VPC CFN Mappings

        :param vpc_settings:
        :param ecs_composex.common.settings.ComposeXSettings settings:
        :return:
        """
        self.mappings = {
            VPC_ID.title: {
                VPC_ID.title: vpc_settings[VPC_ID.title]
            },
            APP_SUBNETS.title: {
                "Ids": vpc_settings[APP_SUBNETS.title]
            },
            STORAGE_SUBNETS.title: {
                "Ids": vpc_settings[STORAGE_SUBNETS.title]
            },
            PUBLIC_SUBNETS.title: {
                "Ids": vpc_settings[PUBLIC_SUBNETS.title]
            },
        }
        ignored_keys = ["RoleArn", "session"]
        self.subnets_parameters.append(APP_SUBNETS)
        self.subnets_parameters.append(PUBLIC_SUBNETS)
        self.subnets_parameters.append(STORAGE_SUBNETS)
        for setting_name in vpc_settings:
            if (setting_name not in self.mappings.keys()
                    and setting_name not in ignored_keys):
                self.mappings[setting_name] = {
                    "Ids": vpc_settings[setting_name]
                }
                param = Parameter(setting_name, Type=SUBNETS_TYPE)
                self.subnets_parameters.append(param)

        self.set_azs_from_vpc_import(
            vpc_settings,
            session=vpc_settings["session"] if keyisset(
                "session", vpc_settings) else None,
        )
def set_ecs_cluster_logging_kms_access(
    settings: ComposeXSettings, policy, role_stack: ComposeXStack
):
    """
    Based on ECS Cluster settings / configurations, grant permissions to KMS key encrypting Log defined to log
    ECS Execute command feature

    :param ecs_composex.common.settings.ComposeXSettings settings:
    :param policy:
    :param ecs_composex.common.stacks.ComposeXStack role_stack:
    """
    if settings.ecs_cluster.log_key and settings.ecs_cluster.log_key != NoValue:
        parameter = Parameter("EcsExecuteLoggingEncryptionKey", Type="String")
        add_parameters(role_stack.stack_template, [parameter])
        if isinstance(settings.ecs_cluster.log_key, FindInMap):
            role_stack.Parameters.update(
                {parameter.title: settings.ecs_cluster.log_key}
            )
        else:
            role_stack.Parameters.update(
                {
                    parameter.title: GetAtt(
                        settings.ecs_cluster.log_key.cfn_resource, "Arn"
                    )
                }
            )
        policy.PolicyDocument["Statement"].append(
            {
                "Action": [
                    "kms:Encrypt*",
                    "kms:Decrypt*",
                    "kms:ReEncrypt*",
                    "kms:GenerateDataKey*",
                    "kms:Describe*",
                ],
                "Resource": [Ref(parameter)],
                "Effect": "Allow",
            }
        )
Beispiel #8
0
def generate_tags_parameters(tags):
    """
    Function to generate a list of parameters used for the tags values

    :return: list of parameters and tags to add to objects
    :rtype: tuple
    """
    parameters = []
    for tag in tags:
        parameters.append(
            Parameter(
                define_tag_parameter_title(tag["Key"]) if isinstance(
                    tags, list) else define_tag_parameter_title(tag),
                group_label="Tagging",
                Type="String",
                MinLength=2,
                MaxLength=128,
                AllowedPattern=r"[\x20-\x7E]+",
                ConstraintDescription="Must be ASCII",
                Default=tag["Value"] if isinstance(tags, list) else tags[tag],
            ))
    return parameters
Beispiel #9
0
    def generate_outputs(self):
        """
        Method to create the outputs for XResources
        """
        if self.stack and not self.stack.is_void:
            root_stack = self.stack.title
        else:
            root_stack = self.mapping_key
        for (
                attribute_parameter,
                output_definition,
        ) in self.output_properties.items():
            output_name = f"{self.logical_name}{attribute_parameter.title}"

            value = self.set_new_resource_outputs(output_definition)
            self.attributes_outputs[attribute_parameter] = {
                "Name":
                output_name,
                "Output":
                Output(output_name, Value=value),
                "ImportParameter":
                Parameter(
                    output_name,
                    group_label="ECS IAM Settings",
                    return_value=attribute_parameter.return_value,
                    Type=attribute_parameter.Type,
                ),
                "ImportValue":
                GetAtt(
                    root_stack,
                    f"Outputs.{output_name}",
                ),
                "Original":
                attribute_parameter,
            }
        for attr in self.attributes_outputs.values():
            if keyisset("Output", attr):
                self.outputs.append(attr["Output"])
Beispiel #10
0
def set_compose_services_ingress(root_stack, dst_family: ComposeFamily,
                                 families: list,
                                 settings: ComposeXSettings) -> None:
    """
    Function to crate SG Ingress between two families / services.
    Presently, the ingress rules are set after all services have been created

    :param ecs_composex.common.stacks.ComposeXStack root_stack:
    :param ecs_composex.ecs.ecs_family.ComposeFamily dst_family:
    :param list families: The list of family names.
    :param ecs_composex.common.settings.ComposeXSettings settings:
    """
    for service in dst_family.service_networking.ingress.services:
        service_name = service["Name"]
        if service_name not in families:
            raise KeyError(
                f"The service {service_name} is not among the services created together. Valid services are",
                families,
            )
        if not keypresent("DependsOn", service):
            add_independent_rules(dst_family, service_name, root_stack)
        else:
            src_family = settings.families[service_name]
            if dst_family.stack.title not in src_family.stack.DependsOn:
                src_family.stack.DependsOn.append(dst_family.stack.title)
            dst_family_sg_param = Parameter(f"{dst_family.stack.title}GroupId",
                                            Type=SG_ID_TYPE)
            add_parameters(src_family.template, [dst_family_sg_param])
            src_family.stack.Parameters.update({
                dst_family_sg_param.title:
                GetAtt(
                    dst_family.stack.title,
                    f"Outputs.{dst_family.logical_name}GroupId",
                ),
            })
            add_dependant_ingress_rules(dst_family, dst_family_sg_param,
                                        src_family)
Beispiel #11
0
"""
Module for DNS Route53 parameters
"""
import re

from ecs_composex.common.cfn_params import Parameter

TAGGING_API_ID = "route53"

ZONES_PATTERN = re.compile(r"^Z[0-9A-Z]+$")
LAST_DOT_RE = re.compile(r"(\.{1}$)")

PUBLIC_DNS_ZONE_ID_T = "PublicDnsZoneId"
PUBLIC_DNS_ZONE_ID = Parameter(
    PUBLIC_DNS_ZONE_ID_T,
    return_value="Id",
    Type="String",
    AllowedPattern=ZONES_PATTERN.pattern,
)

PUBLIC_DNS_ZONE_ARN_T = "PublicDnsZoneArn"
PUBLIC_DNS_ZONE_ARN = Parameter(
    PUBLIC_DNS_ZONE_ARN_T,
    Type="String",
)

PUBLIC_DNS_ZONE_NAME_T = "HostedZoneName"
PUBLIC_DNS_ZONE_NAME = Parameter(PUBLIC_DNS_ZONE_NAME_T, Type="String")


def validate_domain_name(new_record, base_domain):
    """
# SPDX-License-Identifier: MPL-2.0
# Copyright 2020-2022 John Mille <*****@*****.**>

from os import path

from ecs_composex.common import NONALPHANUM
from ecs_composex.common.cfn_params import Parameter
from ecs_composex.common.ecs_composex import X_KEY

MOD_KEY = path.basename(path.dirname(path.abspath(__file__)))
RES_KEY = f"{X_KEY}{MOD_KEY}"
MAPPINGS_KEY = NONALPHANUM.sub("", MOD_KEY)

SSM_PARAM_NAME_T = "ParameterName"
SSM_PARAM_NAME = Parameter(SSM_PARAM_NAME_T, Type="String")

SSM_PARAM_ARN_T = "ParameterArn"
SSM_PARAM_ARN = Parameter(SSM_PARAM_ARN_T, Type="String")

SSM_PARAM_TYPE_T = "ParameterType"
SSM_PARAM_TYPE = Parameter(
    SSM_PARAM_TYPE_T,
    return_value="Type",
    Type="String",
    AllowedValues=["String", "StringList", "SecureString"],
)

SSM_PARAM_KMS_KEY_T = "ParameterKeyId"
SSM_PARAM_KMS_KEY = Parameter(SSM_PARAM_KMS_KEY_T,
                              return_value="KeyId",
                              Type="String")
# SPDX-License-Identifier: MPL-2.0
# Copyright 2020-2022 John Mille <*****@*****.**>

from ecs_composex.common.cfn_params import Parameter

STREAM_ID_T = "StreamId"
STREAM_ARN_T = "Arn"
STREAM_KMS_KEY_ID_T = "KmsKeyId"

GROUP_LABEL = "Kinesis Data Stream"

STREAM_ID = Parameter(STREAM_ID_T, group_label=GROUP_LABEL, Type="String")
STREAM_ARN = Parameter(
    STREAM_ARN_T, group_label=GROUP_LABEL, return_value="Arn", Type="String"
)
STREAM_KMS_KEY_ID = Parameter(
    STREAM_KMS_KEY_ID_T, group_label=GROUP_LABEL, Type="String"
)
Beispiel #14
0
# SPDX-License-Identifier: MPL-2.0
# Copyright 2020-2022 John Mille <*****@*****.**>

from ecs_composex.common.cfn_params import Parameter

TAGGING_API_ID = "sqs"

SQS_SETTINGS = "SQS Settings"

SQS_URL_T = "Url"
SQS_URL = Parameter(SQS_URL_T, group_label=SQS_SETTINGS, Type="String")

SQS_ARN_T = "Arn"
SQS_ARN = Parameter(SQS_ARN_T,
                    group_label=SQS_SETTINGS,
                    return_value="Arn",
                    Type="String")

SQS_NAME_T = "QueueName"
SQS_NAME = Parameter(SQS_NAME_T,
                     group_label=SQS_SETTINGS,
                     return_value="QueueName",
                     Type="String")

DLQ_NAME_T = "DeadLetterQueueName"
DLQ_NAME = Parameter(DLQ_NAME_T, group_label=SQS_SETTINGS, Type="String")

DLQ_ARN_T = "DeadLetterQueueArn"
DLQ_ARN = Parameter(DLQ_ARN_T, group_label=SQS_SETTINGS, Type="String")

SQS_KMS_KEY_T = "QueueKmsKey"
AZS_TYPE = "List<AWS::EC2::AvailabilityZone::Name>"
SG_ID_TYPE = "AWS::EC2::SecurityGroup::Id"
SG_NAME_TYPE = "AWS::EC2::SecurityGroup::GroupName"

DEFAULT_VPC_CIDR = "100.64.72.0/24"
DEFAULT_SINGLE_NAT = True

VPC_SETTINGS = "VPC Settings"

VPC_T = "Vpc"
IGW_T = "InternetGatewayV4"

RES_KEY = "x-vpc"
MOD_KEY = "vpc"
VPC_ID_T = "VpcId"
VPC_ID = Parameter(VPC_ID_T, group_label=VPC_SETTINGS, Type=VPC_TYPE)

VPC_CIDR_T = "VpcCidr"
VPC_CIDR = Parameter(VPC_CIDR_T,
                     group_label=VPC_SETTINGS,
                     Type="String",
                     Default=DEFAULT_VPC_CIDR)

VPC_SINGLE_NAT_T = "SingleNat"
VPC_SINGLE_NAT = Parameter(VPC_SINGLE_NAT_T,
                           group_label=VPC_SETTINGS,
                           Type="String",
                           Default="True")

STORAGE_SUBNETS_CIDR_T = "StorageSubnetsCidr"
STORAGE_SUBNETS_CIDR = Parameter(STORAGE_SUBNETS_CIDR_T,
# SPDX-License-Identifier: MPL-2.0
# Copyright 2020-2022 John Mille <*****@*****.**>

from os import path

from ecs_composex.common.cfn_params import Parameter
from ecs_composex.common.ecs_composex import X_KEY

RES_KEY = f"{X_KEY}{path.basename(path.dirname(path.abspath(__file__)))}"

LABEL = "CloudWatch Alarms"

ALARM_NAME_T = "AlarmName"
ALARM_NAME = Parameter(ALARM_NAME_T, group_label=LABEL, Type="String")

ALARM_ARN_T = "AlarmArn"
ALARM_ARN = Parameter(ALARM_ARN_T,
                      group_label=LABEL,
                      return_value="Arn",
                      Type="String")
Beispiel #17
0
# SPDX-License-Identifier: MPL-2.0
# Copyright 2020-2022 John Mille <*****@*****.**>

from ecs_composex.common.cfn_params import Parameter

S3_ARN_REGEX = r"arn:(aws|aws-gov|aws-cn):s3:::([a-zA-Z0-9-.]+$)"

GROUP_LABEL = "S3"

S3_BUCKET_ARN_T = "BucketArn"
S3_BUCKET_ARN = Parameter(
    S3_BUCKET_ARN_T,
    group_label=GROUP_LABEL,
    return_value="Arn",
    Type="String",
    AllowedPattern=S3_ARN_REGEX,
)
S3_BUCKET_NAME_T = "BucketName"
S3_BUCKET_NAME = Parameter(
    S3_BUCKET_NAME_T,
    group_label=GROUP_LABEL,
    Type="String",
    AllowedPattern=r"^[a-z0-9-.]+$",
)
S3_BUCKET_DOMAIN_NAME_T = "BucketDomainName"
S3_BUCKET_DOMAIN_NAME = Parameter(
    S3_BUCKET_DOMAIN_NAME_T,
    group_label=GROUP_LABEL,
    return_value="DomainName",
    Type="String",
)
    from ecs_composex.ecs.ecs_family import ComposeFamily

from itertools import chain

from compose_x_common.compose_x_common import keyisset
from troposphere import If, NoValue, Ref, Sub
from troposphere.ecs import FirelensConfiguration

from ecs_composex.common import LOG, add_parameters
from ecs_composex.common.cfn_params import Parameter
from ecs_composex.ecs.ecs_conditions import USE_FARGATE_CON_T
from ecs_composex.ecs.managed_sidecars import ManagedSidecar

FLUENT_BIT_IMAGE_PARAMETER = Parameter(
    "FluentBitAwsImage",
    Type="AWS::SSM::Parameter::Value<String>",
    Default="/aws/service/aws-for-fluent-bit/latest",
)

FLUENT_BIT_AGENT_NAME = "log_router"
DEFAULT_LIMIT = 64


def render_agent_config(
    family: ComposeFamily,
    api_health_enabled: bool = False,
    enable_prometheus: bool = False,
    memory_limits: int = DEFAULT_LIMIT,
) -> dict:
    if memory_limits > 512:
        LOG.error(
Beispiel #19
0
 def generate_outputs(self):
     """
     Method to create the outputs for XResources
     """
     if self.stack and not self.stack.is_void:
         root_stack = self.stack.title
     else:
         root_stack = self.module.mapping_key
     if self.lookup_properties:
         for attribute_parameter, value in self.lookup_properties.items():
             output_name = f"{self.logical_name}{attribute_parameter.title}"
             self.attributes_outputs[attribute_parameter] = {
                 "Name":
                 output_name,
                 "ImportValue":
                 self.set_attributes_from_mapping(attribute_parameter),
                 "ImportParameter":
                 Parameter(
                     output_name,
                     group_label=attribute_parameter.group_label
                     if attribute_parameter.group_label else
                     self.module.mod_key,
                     return_value=attribute_parameter.return_value,
                     Type=attribute_parameter.Type,
                 ),
             }
     elif self.output_properties and not self.lookup_properties:
         for (
                 attribute_parameter,
                 output_definition,
         ) in self.output_properties.items():
             output_name = NONALPHANUM.sub("", output_definition[0])
             settings = self.set_new_resource_outputs(
                 output_definition, attribute_parameter)
             value = settings[0]
             export = settings[1]
             self.attributes_outputs[attribute_parameter] = {
                 "Name":
                 output_name,
                 "Output":
                 Output(output_name, Value=value, Export=export),
                 "ImportParameter":
                 Parameter(
                     output_name,
                     group_label=attribute_parameter.group_label
                     if attribute_parameter.group_label else
                     self.module.mod_key,
                     return_value=attribute_parameter.return_value,
                     Type=attribute_parameter.Type,
                 ),
                 "ImportValue":
                 GetAtt(
                     root_stack,
                     f"Outputs.{output_name}",
                 ),
                 "Original":
                 attribute_parameter,
             }
     for attr in self.attributes_outputs.values():
         if keyisset("Output", attr):
             self.outputs.append(attr["Output"])
# SPDX-License-Identifier: MPL-2.0
# Copyright 2020-2022 John Mille <*****@*****.**>

import re
from os import path

from ecs_composex.common.cfn_params import Parameter
from ecs_composex.common.ecs_composex import X_KEY

MOD_KEY = path.basename(path.dirname(path.abspath(__file__)))
RES_KEY = f"{X_KEY}{MOD_KEY}"

TOPIC_ARN_RE = re.compile(r"(^arn:aws(?:-[a-z]+)?:sns:[\S]+:[0-9]+:[\S]+)$")

TOPIC_ARN_T = "TopicArn"
TOPIC_NAME_T = "TopicName"
TOPIC_KMS_KEY_T = "TopicKmsKey"

TOPIC_ARN = Parameter(TOPIC_ARN_T, Type="String")
TOPIC_NAME = Parameter(TOPIC_NAME_T, return_value="TopicName", Type="String")
TOPIC_KMS_KEY = Parameter(TOPIC_KMS_KEY_T,
                          return_value="KmsMasterKeyId",
                          Type="String")
#  SPDX-License-Identifier: MPL-2.0
#  Copyright 2020-2022 John Mille <*****@*****.**>
"""
Simple class to manage AWS XRay sidecar
"""

from ecs_composex.common.cfn_params import Parameter
from ecs_composex.ecs.managed_sidecars import ManagedSidecar

CW_IMAGE_PARAMETER = Parameter(
    "CloudwatchAgentImage",
    Type="String",
    Default="public.ecr.aws/cloudwatch-agent/cloudwatch-agent:latest",
)

CW_AGENT_NAME = "cloudwatch-agent"
CW_AGENT_DEFINITION = {
    "image": CW_IMAGE_PARAMETER.Default,
    "deploy": {
        "resources": {
            "limits": {
                "cpus": 0.1,
                "memory": "256M"
            }
        },
    },
    "labels": {
        "container_name": "cw-agent"
    },
}
from os import path

from ecs_composex.common import NONALPHANUM
from ecs_composex.common.cfn_params import Parameter
from ecs_composex.common.ecs_composex import X_KEY

MOD_KEY = path.basename(path.dirname(path.abspath(__file__)))
RES_KEY = f"{X_KEY}{MOD_KEY}"
MAPPINGS_KEY = NONALPHANUM.sub("", MOD_KEY)

ROLE_ID_RE = re.compile(r"^[A-Z0-9]+$")

POLICY_RE = re.compile(
    r"((^([a-zA-Z0-9-_./]+)$)|(^(arn:aws:iam::(aws|\d{12}):policy/)[a-zA-Z0-9-_./]+$))"
)


IAM_ROLE_T = "IamRoleName"
IAM_ROLE = Parameter(IAM_ROLE_T, return_value=None, Type="String")

IAM_ROLE_ARN_T = "IamRoleArn"
IAM_ROLE_ARN = Parameter(IAM_ROLE_ARN_T, return_value="Arn", Type="String")

IAM_ROLE_ID_T = "IamRoleId"
IAM_ROLE_ID = Parameter(
    IAM_ROLE_ID_T,
    return_value="RoleId",
    Type="String",
    AllowedPattern=ROLE_ID_RE.pattern,
)
Beispiel #23
0
from ecs_composex.common import NONALPHANUM
from ecs_composex.common.cfn_params import Parameter
from ecs_composex.common.ecs_composex import X_KEY
from ecs_composex.vpc.vpc_params import SG_ID_TYPE

MOD_KEY = path.basename(path.dirname(path.abspath(__file__)))
RES_KEY = f"{X_KEY}{MOD_KEY}"
MAPPINGS_KEY = NONALPHANUM.sub("", MOD_KEY)

LB_ID_T = "elbv2Id"
LB_ARN_T = "elbv2Arn"
LB_SG_ID_T = "elbv2SecurityGroupId"
LB_DNS_NAME_T = "DNSName"
LB_DNS_ZONE_ID_T = "CanonicalHostedZoneID"

LB_ID = Parameter(LB_ID_T, Type="String")
LB_ARN = Parameter(LB_ARN_T, Type="String")
LB_SG_ID = Parameter(LB_SG_ID_T, return_value="GroupId", Type=SG_ID_TYPE)
LB_DNS_NAME = Parameter(LB_DNS_NAME_T, return_value="DNSName", Type="String")
LB_DNS_ZONE_ID = Parameter(
    LB_DNS_ZONE_ID_T,
    return_value="CanonicalHostedZoneID",
    Type="String",
    AllowedPattern=r"^Z[0-9A-Z]+$",
)
LB_NAME_T = "LoadBalancerName"
LB_NAME = Parameter(LB_NAME_T, return_value="LoadBalancerName", Type="String")
LB_FULL_NAME_T = "LoadBalancerFullName"
LB_FULL_NAME = Parameter(LB_FULL_NAME_T,
                         return_value="LoadBalancerFullName",
                         Type="String")
Beispiel #24
0
# SPDX-License-Identifier: MPL-2.0
# Copyright 2020-2022 John Mille <*****@*****.**>
"""
Module for Secrets parameters
"""

from ecs_composex.common.cfn_params import Parameter

RES_KEY = "secrets"
XRES_KEY = "x-secrets"

PASSWORD_LENGTH_T = "PasswordLength"
PASSWORD_LENGTH = Parameter(PASSWORD_LENGTH_T,
                            Type="Number",
                            MinValue=8,
                            MaxValue=32,
                            Default=16)

USERNAME_T = "Username"
USERNAME = Parameter(USERNAME_T,
                     Type="String",
                     MinLength=3,
                     MaxLength=16,
                     Default="dbadmin")
# SPDX-License-Identifier: MPL-2.0
# Copyright 2020-2022 John Mille <*****@*****.**>

import re
from os import path

from ecs_composex.common import NONALPHANUM
from ecs_composex.common.cfn_params import Parameter
from ecs_composex.common.ecs_composex import X_KEY

MOD_KEY = path.basename(path.dirname(path.abspath(__file__)))
RES_KEY = f"{X_KEY}{MOD_KEY}"
MAPPINGS_KEY = NONALPHANUM.sub("", MOD_KEY)

KMS_KEY_ARN_RE = re.compile(
    r"(?:^arn:aws(?:-[a-z]+)?:kms:[\S]+:[0-9]+:)((key/)([\S]+))$")
KMS_ALIAS_ARN_RE = re.compile(
    r"(?:^arn:aws(?:-[a-z]+)?:kms:[\S]+:[0-9]+:)((alias/)([\S]+))$")

KMS_KEY_ARN_T = "KmsKeyArn"
KMS_KEY_ID_T = "KmsKeyId"
KMS_KEY_ALIAS_NAME_T = "KmsKeyAliasName"
KMS_KEY_ALIAS_ARN_T = "KmsKeyAliasArn"

KMS_KEY_ID = Parameter(KMS_KEY_ID_T, return_value="KeyId", Type="String")
KMS_KEY_ARN = Parameter(KMS_KEY_ARN_T, return_value="Arn", Type="String")
KMS_KEY_ALIAS_NAME = Parameter(KMS_KEY_ALIAS_NAME_T, Type="String")
# SPDX-License-Identifier: MPL-2.0
# Copyright 2020-2022 John Mille <*****@*****.**>

from ecs_composex.common.cfn_params import Parameter
from ecs_composex.rds.rds_params import (
    DB_ENDPOINT_ADDRESS_T,
    DB_ENDPOINT_PORT_T,
    DB_RO_ENDPOINT_ADDRESS_T,
)

DB_CLUSTER_RESOURCES_ARN_T = "DBClusterResources"
DB_CLUSTER_RESOURCES_ARN = Parameter(DB_CLUSTER_RESOURCES_ARN_T, Type="String")

DB_RESOURCE_ID_T = "ClusterResourceId"
DB_RESOURCE_ID = Parameter(DB_RESOURCE_ID_T,
                           return_value=DB_RESOURCE_ID_T,
                           Type="String")

DB_ENDPOINT = Parameter(DB_ENDPOINT_ADDRESS_T,
                        return_value="Endpoint",
                        Type="String")
DB_READ_ENDPOINT = Parameter(DB_RO_ENDPOINT_ADDRESS_T,
                             return_value="ReadEndpoint",
                             Type="String")
DB_PORT = Parameter(
    DB_ENDPOINT_PORT_T,
    return_value="Port",
    Type="Number",
    MinValue=1,
    MaxValue=((2 ^ 16) - 1),
)
from os import path

from ecs_composex.common import NONALPHANUM
from ecs_composex.common.cfn_params import Parameter
from ecs_composex.common.ecs_composex import X_KEY

MOD_KEY = f"{path.basename(path.dirname(path.abspath(__file__)))}"
RES_KEY = f"{X_KEY}{MOD_KEY}"
MAPPINGS_KEY = NONALPHANUM.sub("", MOD_KEY)


VALIDATION_DOMAIN_NAME_T = "ValidationDomainName"
VALIDATION_DOMAIN_NAME = Parameter(
    VALIDATION_DOMAIN_NAME_T,
    Type="String",
    Default="none",
    AllowedPattern=r"(^none$|^(\*\.)?(((?!-)[A-Za-z0-9-]{0,62}[A-Za-z0-9])\.)+((?!-)[A-Za-z0-9-]{1,62}[A-Za-z0-9])$)",
)

VALIDATION_DOMAIN_ZONE_ID_T = "ValidationZoneId"
VALIDATION_DOMAIN_ZONE_ID = Parameter(
    VALIDATION_DOMAIN_ZONE_ID_T,
    Type="String",
    AllowedPattern=r"(none|^Z[A-Z0-9]+$)",
    Default="none",
)

CERT_CN_T = "CertificateCn"
CERT_CN = Parameter(
    CERT_CN_T,
    Type="String",
Beispiel #28
0
#  SPDX-License-Identifier: MPL-2.0
#  Copyright 2020-2022 John Mille <*****@*****.**>

"""
OpenSearch parameters
"""
import re

from ecs_composex.common.cfn_params import Parameter
from ecs_composex.vpc.vpc_params import SG_ID_TYPE

OS_DOMAIN_ID_T = "DomainId"
OS_DOMAIN_ID = Parameter(OS_DOMAIN_ID_T, Type="String")

OS_DOMAIN_ARN_T = "DomainArn"
OS_DOMAIN_ARN = Parameter(OS_DOMAIN_ARN_T, return_value="Arn", Type="String")

OS_DOMAIN_ENDPOINT_T = "DomainEndpoint"
OS_DOMAIN_ENDPOINT = Parameter(
    OS_DOMAIN_ENDPOINT_T, return_value="DomainEndpoint", Type="String"
)

OS_DOMAIN_SG_T = "DomainSg"
OS_DOMAIN_SG = Parameter(OS_DOMAIN_SG_T, return_value="GroupId", Type=SG_ID_TYPE)

OS_DOMAIN_PORT_T = "DomainPort"
OS_DOMAIN_PORT = Parameter(
    OS_DOMAIN_PORT_T, Type="Number", Default=443, MinValue=0, MaxValue=(pow(2, 16) - 1)
)

OS_DOMAIN_ARN_RE = re.compile(
Beispiel #29
0
def define_service_targets(stack, rule, cluster_arn):
    """
    Function to define the targets for service.

    :param ecs_composex.events.events_stack.XStack stack:
    :param ecs_composex.events.events_stack.Rule rule:
    :param troposphere.Sub cluster_arn:
    :return:
    """
    for service in rule.families_targets:
        service_sg_param = Parameter(f"{service[0].logical_name}GroupId",
                                     Type=SG_ID_TYPE)
        service_task_def_param = Parameter(
            f"{service[0].logical_name}{TASK_T}", Type="String")
        service_subnets_param = Parameter(
            f"{service[0].logical_name}{APP_SUBNETS.title}", Type=SUBNETS_TYPE)
        events_policy_doc = {
            "Version":
            "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": ["ecs:RunTask"],
                    "Resource": [Ref(service_task_def_param)],
                    "Condition": {
                        "ArnLike": {
                            "ecs:cluster": cluster_arn
                        }
                    },
                },
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": ["*"],
                    "Condition": {
                        "StringLike": {
                            "iam:PassedToService":
                            Sub(f"ecs-tasks.${{{AWS_URL_SUFFIX}}}")
                        }
                    },
                },
            ],
        }
        task_events_policy_doc = {
            "Version":
            "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": ["ecs:RunTask"],
                    "Resource": [Ref(service[0].template.resources[TASK_T])],
                    "Condition": {
                        "ArnLike": {
                            "ecs:cluster": cluster_arn
                        }
                    },
                },
                {
                    "Effect": "Allow",
                    "Action": "iam:PassRole",
                    "Resource": ["*"],
                    "Condition": {
                        "StringLike": {
                            "iam:PassedToService":
                            Sub(f"ecs-tasks.${{{AWS_URL_SUFFIX}}}")
                        }
                    },
                },
            ],
        }
        events_policy = Policy(PolicyName="EventsAccess",
                               PolicyDocument=events_policy_doc)
        if "EventsAccessPolicy" not in service[0].template.resources:
            service[0].template.add_resource(
                PolicyType(
                    "EventsAccessPolicy",
                    PolicyName="EventsAccess",
                    PolicyDocument=task_events_policy_doc,
                    Roles=[
                        service[0].iam_manager.task_role.name,
                        service[0].iam_manager.exec_role.name,
                    ],
                ))
        role_name = f"{rule.logical_name}IamRoleToTrigger{service[0].logical_name}"
        if role_name not in stack.stack_template.resources:
            role = stack.stack_template.add_resource(
                Role(
                    f"{rule.logical_name}IamRoleToTrigger{service[0].logical_name}",
                    AssumeRolePolicyDocument={
                        "Version":
                        "2012-10-17",
                        "Statement": [{
                            "Sid": "TrustPolicy",
                            "Effect": "Allow",
                            "Principal": {
                                "Service": Sub(f"events.${{{AWS_URL_SUFFIX}}}")
                            },
                            "Action": "sts:AssumeRole",
                        }],
                    },
                    ManagedPolicyArns=[],
                    Policies=[events_policy],
                    PermissionsBoundary=Ref(AWS_NO_VALUE),
                ))
            if service[0].iam_manager.permissions_boundary:
                role.PermissionsBoundary = service[
                    0].iam_manager.permissions_boundary
        else:
            role = stack.stack_template.resources[role_name]
        add_parameters(
            stack.stack_template,
            [service_sg_param, service_task_def_param, service_subnets_param],
        )
        stack.Parameters.update({
            service_sg_param.title:
            GetAtt(
                service[0].logical_name,
                f"Outputs.{service[0].logical_name}GroupId",
            ),
            service_task_def_param.title:
            GetAtt(
                service[0].logical_name,
                f"Outputs.{service[0].task_definition.title}",
            ),
            service_subnets_param.title:
            GetAtt(
                service[0].logical_name,
                f"Outputs.{SERVICE_SUBNETS.title}",
            ),
        })
        target = Target(
            EcsParameters=EcsParameters(
                NetworkConfiguration=NetworkConfiguration(
                    AwsVpcConfiguration=AwsVpcConfiguration(
                        Subnets=Ref(service_subnets_param),
                        SecurityGroups=[Ref(service_sg_param)],
                        AssignPublicIp=service[0].service_networking.
                        eip_assign,
                    )),
                PlatformVersion=Ref(FARGATE_VERSION),
                TaskCount=service[3],
                TaskDefinitionArn=Ref(service_task_def_param),
                LaunchType="FARGATE",
            ),
            Arn=cluster_arn,
            Id=service[0].logical_name,
            RoleArn=GetAtt(role, "Arn"),
        )
        rule.cfn_resource.Targets.append(target)
        if service[0].logical_name not in stack.DependsOn:
            stack.DependsOn.append(service[0].logical_name)
        if (keyisset("DeleteDefaultService", service[4])
                and SERVICE_T in service[0].template.resources):
            LOG.info(
                f"Deleting ECS Service definition from stack for {service[0].name}"
            )
            del service[0].template.resources[SERVICE_T]
        if SERVICE_SCALING_TARGET in service[0].template.resources:
            LOG.warning(
                f"Target for event {rule.logical_name} also had scaling rules. Deleting"
            )
            delete_service_from_template(service)
Beispiel #30
0
# SPDX-License-Identifier: MPL-2.0
# Copyright 2020-2022 John Mille <*****@*****.**>

from ecs_composex.common.cfn_params import Parameter
from ecs_composex.rds.rds_params import (
    DB_ENDPOINT_ADDRESS_T,
    DB_ENDPOINT_PORT_T,
    DB_RO_ENDPOINT_ADDRESS_T,
)

DOCDB_NAME_T = "DBClusterName"
DOCDB_ID_T = "ClusterResourceId"

DOCDB_NAME = Parameter(DOCDB_NAME_T, Type="String")
DOCDB_ID = Parameter(DOCDB_ID_T,
                     return_value="ClusterResourceId",
                     Type="String")
DOCDBC_ENDPOINT = Parameter(DB_ENDPOINT_ADDRESS_T,
                            return_value="Endpoint",
                            Type="String")
DOCDBC_READ_ENDPOINT = Parameter(DB_RO_ENDPOINT_ADDRESS_T,
                                 return_value="ReadEndpoint",
                                 Type="String")
DOCDB_PORT = Parameter(
    DB_ENDPOINT_PORT_T,
    return_value="Port",
    Type="Number",
    MinValue=1,
    Default="27017",
    MaxValue=((2 ^ 16) - 1),
)