def _get_resources(self):
        resources = [
            Resource(
                "CoreOSSecurityGroup", "AWS::EC2::SecurityGroup",
                Properties({
                    "VpcId": {
                        "Ref": "VPC"
                    },
                    "GroupDescription":
                    "CoreOS SecurityGroup",
                    "SecurityGroupIngress": [{
                        "CidrIp": "10.0.0.0/16",
                        "IpProtocol": "udp",
                        "FromPort": "0",
                        "ToPort": "65535"
                    }, {
                        "CidrIp": "10.0.0.0/16",
                        "IpProtocol": "icmp",
                        "FromPort": "-1",
                        "ToPort": "-1"
                    }],
                    "Tags": [{
                        "Key": "Name",
                        "Value": "CoreOSSecurityGroup"
                    }]
                })),
            Resource(
                "CoreOSSecurityGroup2380Ingress",
                "AWS::EC2::SecurityGroupIngress",
                Properties({
                    "GroupId": {
                        "Ref": "CoreOSSecurityGroup"
                    },
                    "IpProtocol": "tcp",
                    "FromPort": "2380",
                    "ToPort": "2380",
                    # "SourceSecurityGroupId": {"Ref": "CoreOSSecurityGroup"}  # TODO not working for now because need to use fleetctl locally to load units
                    "CidrIp": "10.0.0.0/16"
                }),
                attributes=[DependsOn("CoreOSSecurityGroup")]),
            Resource(
                "CoreOSSecurityGroup2379Ingress",
                "AWS::EC2::SecurityGroupIngress",
                Properties({
                    "GroupId": {
                        "Ref": "CoreOSSecurityGroup"
                    },
                    "IpProtocol": "tcp",
                    "FromPort": "2379",
                    "ToPort": "2379",
                    # "SourceSecurityGroupId": {"Ref": "CoreOSSecurityGroup"}  # TODO not working for now because need to use fleetctl locally to load units
                    "CidrIp": "10.0.0.0/16"
                }),
                attributes=[DependsOn("CoreOSSecurityGroup")])
        ]

        resources += self._get_etcd_cluster_resources()
        resources += self._get_coreos_resources()
        return resources
    def _get_resources(self):
        resources = []
        dns_suffix = self.data['dns_suffix']
        for prefix in self.DNS_MAPPING:
            name = self._get_dns_record_name(prefix)

            if prefix != '':
                prefix = "%s." % prefix

            resources.append(
                Resource(
                    name, "AWS::Route53::RecordSet",
                    Properties({
                        "HostedZoneName":
                        dns_suffix,
                        "Comment":
                        "DNS name for TeamCity",
                        "Name": {
                            "Fn::Join": [
                                "",
                                [prefix, {
                                    "Ref": "EnvName"
                                }, '.', dns_suffix]
                            ]
                        },
                        "Type":
                        "CNAME",
                        "TTL":
                        "60",
                        "ResourceRecords": [{
                            "Fn::GetAtt":
                            ["PublicELB", "CanonicalHostedZoneName"]
                        }]
                    })))
        return resources
    def _get_resources(self):
        resources = [
            Resource(
                "VPC", "AWS::EC2::VPC",
                Properties({
                    "CidrBlock": {
                        "Fn::FindInMap": ["SubnetConfig", "VPC", "CIDR"]
                    },
                    "EnableDnsSupport":
                    "true",
                    "EnableDnsHostnames":
                    "true",
                    "Tags": [{
                        "Key": "Application",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }]
                })),
            Resource(
                "InternetGateway", "AWS::EC2::InternetGateway",
                Properties({
                    "Tags": [{
                        "Key": "Application",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }]
                })),
            Resource(
                "GatewayToInternet", "AWS::EC2::VPCGatewayAttachment",
                Properties({
                    "VpcId": {
                        "Ref": "VPC"
                    },
                    "InternetGatewayId": {
                        "Ref": "InternetGateway"
                    }
                }))
        ]

        resources += self._get_public_subnets()
        resources += self._get_private_subnets()

        return resources
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from cfn_pyplates.core import CloudFormationTemplate, Resource
from cfn_pyplates.core import Properties, options
from utils import nametag

cft = CloudFormationTemplate(description="Tooltool Infrastructure")

rgn = options['region']

# production

cft.resources.add(Resource(
    'FileBucket', 'AWS::S3::Bucket',
    Properties({
        "AccessControl": "Private",
        "BucketName": "mozilla-releng-%s-tooltool" % (rgn,),
        'Tags': [nametag('Tooltool File Storage - %s' % (rgn,))],
    })
))

# staging

cft.resources.add(Resource(
    'StagingFileBucket', 'AWS::S3::Bucket',
    Properties({
        "AccessControl": "Private",
        "BucketName": "mozilla-releng-staging-%s-tooltool" % (rgn,),
        'Tags': [nametag('Tooltool File Storage - Staging - %s' % (rgn,))],
    })
))
Example #5
0
def make_storage_template():
    cft = CloudFormationTemplate(description="Refinery Platform storage")
    # Parameters
    cft.parameters.add(
        Parameter('StaticBucketName', 'String', {
            'Description': 'Name of S3 bucket for Django static files',
        }))
    cft.parameters.add(
        Parameter(
            'MediaBucketName',
            'String',
            {
                'Description':
                'Name of S3 bucket for Django media files',
                # make names DNS-compliant without periods (".") for compatibility
                # with virtual-hosted-style access and S3 Transfer Acceleration
                'AllowedPattern':
                '[a-z0-9\-]+',
                'ConstraintDescription':
                'must only contain lower case letters, numbers, and hyphens',
            }))
    # Resources
    cft.resources.add(
        Resource(
            'StaticStorageBucket',
            'AWS::S3::Bucket',
            Properties({
                'BucketName': ref('StaticBucketName'),
                'AccessControl': 'PublicRead',
                'CorsConfiguration': {
                    'CorsRules': [{
                        'AllowedOrigins': ['*'],
                        'AllowedMethods': ['GET'],
                        'AllowedHeaders': ['Authorization'],
                        'MaxAge': 3000,
                    }]
                },
            }),
            DeletionPolicy('Retain'),
        ))
    cft.resources.add(
        Resource(
            'MediaStorageBucket',
            'AWS::S3::Bucket',
            Properties({
                'BucketName': ref('MediaBucketName'),
                'AccessControl': 'PublicRead',
                'CorsConfiguration': {
                    'CorsRules': [{
                        'AllowedOrigins': ['*'],
                        'AllowedMethods': ['POST', 'PUT', 'DELETE'],
                        'AllowedHeaders': ['*'],
                        'ExposedHeaders': ['ETag'],
                        'MaxAge': 3000,
                    }]
                }
            }),
            DeletionPolicy('Retain'),
        ))
    cft.outputs.add(
        Output('MediaBucketName', ref('MediaStorageBucket'),
               {'Fn::Sub': '${AWS::StackName}Media'},
               'Name of S3 bucket for Django media files'))

    return cft
Example #6
0
def build_template(args):
    """
    Build a CloudFormation template allowing for secure CloudTrail log
    aggregation and fine grained access control to SNS topics for notifications
    of new CloudTrail logs

    The reason that we create IAM roles for each client AWS account in order to
    enable clients to read their own CloudTrail logs, instead of merely
    delegating access to them in an S3 bucket policy is that

    "Bucket owner account can delegate permissions to users in its own account,
    but it cannot delegate permissions to other AWS accounts,
    because cross-account delegation is not supported." :
    http://docs.aws.amazon.com/AmazonS3/latest/dev/example-walkthroughs-managing-access-example4.html

    As a consequence we *can* delegate bucket permissions to client AWS
    accounts but we *can not* delegate object permissions (the log files
    themselves) to client AWS accounts.

    Example config :

    AccountRootARNs:
    - arn:aws:iam::012345678901:root               # Sales
    - arn:aws:iam::123456789012:root               # HR
    - arn:aws:iam::234567890123:root               # Marketing
    CloudTrailLogConsumers:
    - arn:aws:iam::345678901234:user/security_team # Security team user
    - TrustedARN: arn:aws:iam::456789012343:root   # CloudCo Third Party
      TrustingARNs:
      - arn:aws:iam::012345678901:root             # Sales
      - arn:aws:iam::234567890123:root             # Marketing
    - TrustedARN: arn:aws:iam::567890123434:root   # Other.com Third Party
      TrustingARNs:
      - arn:aws:iam::123456789012:root             # HR
    ForeignAccountStatusSubscribers:
    - arn:aws:iam::345678901234:root               # Security Team


    """
    config = args.config
    account_root_arns = (
        config['AccountRootARNs'] if 'AccountRootARNs' in config
        and isinstance(config['AccountRootARNs'], list) else [])

    cft = CloudFormationTemplate(
        description="AWS CloudTrail Storage Account S3 Storage Bucket")

    # Create the bucket
    cft.resources.add(
        Resource("S3Bucket", "AWS::S3::Bucket",
                 {"BucketName": args.bucketname}, DeletionPolicy("Retain")))

    # Build the s3 bucket policy statement list
    bucket_policy_statements = []

    # Allow the CloudTrail system to GetBucketAcl on the CloudTrail storage
    # bucket
    bucket_policy_statements.append({
        "Sid":
        "AWSCloudTrailAclCheck",
        "Effect":
        "Allow",
        "Principal": {
            "Service": "cloudtrail.amazonaws.com"
        },
        "Action": ["s3:GetBucketAcl"],
        "Resource":
        join("", "arn:aws:s3:::", ref("S3Bucket"))
    })

    # Allow each account to read it's own logs
    for account_arn in account_root_arns:
        account_id = get_account_id_from_arn(account_arn)
        cft.resources.add(
            Resource(
                "CloudTrailLogReaderRole%s" % account_id,
                "AWS::CloudFormation::Stack", {
                    "TemplateURL":
                    "https://s3.amazonaws.com/infosec-cloudformation-templates/manage_iam_role.json",
                    "Parameters": {
                        "RoleName": "CloudTrailLogReader%s" % account_id,
                        "TrustedEntities": get_consumer_arns(
                            account_arn, config)
                    },
                    "TimeoutInMinutes": "5"
                }))
        cft.resources.add(
            Resource(
                "CloudTrailLogReaderPolicy%s" % account_id, "AWS::IAM::Policy",
                {
                    "PolicyName": "CloudTrailLogReaderPolicy%s" % account_id,
                    "PolicyDocument": {
                        "Version":
                        "2012-10-17",
                        "Statement": [{
                            "Effect":
                            "Allow",
                            "Action":
                            "s3:GetObject",
                            "Resource":
                            join("", "arn:aws:s3:::", ref("S3Bucket"),
                                 "/AWSLogs/%s/*" % account_id)
                        }]
                    },
                    "Roles": ["CloudTrailLogReader%s" % account_id]
                }, DependsOn("CloudTrailLogReaderRole%s" % account_id)))

    cft.resources.add(
        Resource(
            "ReadCloudTrailBucket", "AWS::IAM::ManagedPolicy", {
                "Description":
                "ReadCloudTrailBucket",
                "PolicyDocument": {
                    "Version":
                    "2012-10-17",
                    "Statement":
                    [{
                        "Effect": "Allow",
                        "Action":
                        ["s3:ListAllMyBuckets", "s3:GetBucketLocation"],
                        "Resource": "*"
                    }, {
                        "Effect":
                        "Allow",
                        "Action": [
                            "s3:GetBucketAcl", "s3:ListBucket",
                            "s3:GetBucketTagging"
                        ],
                        "Resource":
                        join("", "arn:aws:s3:::", ref("S3Bucket"))
                    }]
                },
                "Roles": [
                    "CloudTrailLogReader%s" %
                    get_account_id_from_arn(account_arn)
                    for account_arn in account_root_arns
                ]
            },
            DependsOn([
                "CloudTrailLogReaderRole%s" %
                get_account_id_from_arn(account_arn)
                for account_arn in account_root_arns
            ])))

    bucket_policy_statements.append({
        #       "Sid":"AWSCloudTrailWrite%s" % get_account_id_from_arn(account_arn),
        "Effect":
        "Allow",
        "Principal": {
            "Service": "cloudtrail.amazonaws.com"
        },
        "Action": ["s3:PutObject"],
        "Resource":
        join("", "arn:aws:s3:::", ref("S3Bucket"), "/AWSLogs/*"),
        "Condition": {
            "StringEquals": {
                "s3:x-amz-acl": "bucket-owner-full-control"
            }
        }
    })

    # Apply the bucket policy to the bucket
    cft.resources.add(
        Resource(
            "BucketPolicy", "AWS::S3::BucketPolicy", {
                "Bucket": ref("S3Bucket"),
                "PolicyDocument": {
                    "Id": "BucketPolicyDocument",
                    "Version": "2012-10-17",
                    "Statement": bucket_policy_statements
                }
            }))

    # Create a single SNS Topic that each AWS account can publish to to report
    # on the CloudFormation progress
    cft.resources.add(
        Resource(
            "ForeignAccountStatusTopic", "AWS::SNS::Topic", {
                "DisplayName":
                "Topic for foreign accounts to publish status information to",
                "TopicName": "ForeignAccountStatus"
            }))

    cft.resources.add(
        Resource(
            "ForeignAccountStatusTopicPolicy", "AWS::SNS::TopicPolicy", {
                "Topics": [ref("ForeignAccountStatusTopic")],
                "PolicyDocument": {
                    "Version":
                    "2012-10-17",
                    "Id":
                    "ForeignAccountStatusPolicy",
                    "Statement": [{
                        "Sid": "ForeignAccountStatusPublisher",
                        "Effect": "Allow",
                        "Principal": {
                            "AWS": account_root_arns
                        },
                        "Action": "SNS:Publish",
                        "Resource": ref("ForeignAccountStatusTopic"),
                    }, {
                        "Sid":
                        "ForeignAccountStatusSubscriber",
                        "Effect":
                        "Allow",
                        "Principal": {
                            "AWS": config['ForeignAccountStatusSubscribers']
                        },
                        "Action": [
                            "SNS:GetTopicAttributes",
                            "SNS:ListSubscriptionsByTopic", "SNS:Subscribe"
                        ],
                        "Resource":
                        ref("ForeignAccountStatusTopic"),
                    }]
                }
            }))

    # Create SNS Topics for each AWS account and grant those accounts rights
    # to publish and subscribe to those topics
    for account_arn in account_root_arns:
        account_id = get_account_id_from_arn(account_arn)
        cft.resources.add(
            Resource(
                "Topic%s" % account_id, "AWS::SNS::Topic", {
                    "DisplayName":
                    "Mozilla CloudTrail Logs Topic for Account %s" %
                    account_id,
                    "TopicName":
                    "MozillaCloudTrailLogs%s" % account_id
                }))

        # http://docs.aws.amazon.com/sns/latest/dg/AccessPolicyLanguage_UseCases_Sns.html#AccessPolicyLanguage_UseCase4_Sns
        cft.resources.add(
            Resource(
                "TopicPolicy%s" % account_id, "AWS::SNS::TopicPolicy", {
                    "Topics": [ref("Topic%s" % account_id)],
                    "PolicyDocument": {
                        "Version":
                        "2012-10-17",
                        "Id":
                        "AWSCloudTrailSNSPolicy%s" % account_id,
                        "Statement": [{
                            "Sid": "CloudTrailSNSPublish%s" % account_id,
                            "Effect": "Allow",
                            "Principal": {
                                "Service": "cloudtrail.amazonaws.com"
                            },
                            "Action": "SNS:Publish",
                            "Resource": ref("Topic%s" % account_id)
                        }, {
                            "Sid":
                            "CloudTrailSNSSubscribe%s" % account_id,
                            "Effect":
                            "Allow",
                            "Principal": {
                                "AWS": account_arn
                            },
                            "Action": [
                                "SNS:GetTopicAttributes",
                                "SNS:ListSubscriptionsByTopic", "SNS:Subscribe"
                            ],
                            "Resource":
                            join(":", "arn:aws:sns", ref("AWS::Region"),
                                 ref("AWS::AccountId"),
                                 "MozillaCloudTrailLogs%s" % account_id)
                        }]
                    }
                }))
    return cft
cft.resources.add(Resource(
    name, 'AWS::IAM::User',
    Properties({
        'Policies': [
            policy("tooltoolbucketaccess", {
                "Effect": "Allow",
                "Action": [
                    "s3:ListBucket",
                    "s3:ListBucketMultipartUploads",
                    "s3:ListBucketVersions",
                ],
                "Resource": [
                    bucket_arn('use1'),
                    bucket_arn('usw1'),
                    bucket_arn('usw2')
                ]
            }),
            policy("tooltoolobjectaccess", {
                "Effect": "Allow",
                "Action": [
                    "s3:AbortMultipartUpload",
                    "s3:DeleteObject",
                    "s3:DeleteObjectVersion",
                    "s3:GetObject",
                    "s3:GetObjectAcl",
                    "s3:GetObjectTorrent",
                    "s3:GetObjectVersion",
                    "s3:GetObjectVersionAcl",
                    "s3:GetObjectVersionTorrent",
                    "s3:ListMultipartUploadParts",
                    "s3:PutObject",
                    "s3:PutObjectAcl",
                    "s3:PutObjectVersionAcl",
                    "s3:RestoreObject"
                ],
                "Resource": [
                    object_arn('use1'),
                    object_arn('usw1'),
                    object_arn('usw2')
                ]
            }),
        ]
    })
))
 def _get_resources(self):
     return [
         Resource(
             "PublicELB", "AWS::ElasticLoadBalancing::LoadBalancer",
             Properties({
                 "Subnets": [{
                     "Ref": subnet_name
                 } for subnet_name in self.data['public_subnets']],
                 "SecurityGroups": [{
                     "Ref": "PublicHTTPSecurityGroup"
                 }],
                 "Listeners": [{
                     "LoadBalancerPort": "80",
                     "InstancePort": "8080",
                     "Protocol": "HTTP"
                 }],
                 "HealthCheck": {
                     "Target": "HTTP:8080/",
                     "HealthyThreshold": "3",
                     "UnhealthyThreshold": "5",
                     "Interval": "30",
                     "Timeout": "5"
                 }
             })),
         Resource(
             "PublicELBIAMUser", "AWS::IAM::User",
             Properties({
                 "Policies": [{
                     "PolicyName": "PublicELBRegisterDeregisterOnly",
                     "PolicyDocument": {
                         "Version":
                         "2012-10-17",
                         "Statement": [{
                             "Effect":
                             "Allow",
                             "Action": [
                                 "elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
                                 "elasticloadbalancing:RegisterInstancesWithLoadBalancer"
                             ],
                             "Resource": {
                                 "Fn::Join": [
                                     "",
                                     [
                                         "arn:aws:elasticloadbalancing:", {
                                             "Ref": "AWS::Region"
                                         }, ":", {
                                             "Ref": "AWS::AccountId"
                                         }, ":loadbalancer/", {
                                             "Ref": "PublicELB"
                                         }
                                     ]
                                 ]
                             }
                         }]
                     }
                 }]
             })),
         Resource("PublicELBAccessKey", "AWS::IAM::AccessKey",
                  Properties({"UserName": {
                      "Ref": "PublicELBIAMUser"
                  }}))
     ]
 def _get_resources(self):
     return [
         Resource(
             "PublicHTTPSecurityGroup", "AWS::EC2::SecurityGroup",
             Properties({
                 "VpcId": {
                     "Ref": "VPC"
                 },
                 "GroupDescription":
                 "Ingress for port 80 from anywhere",
                 "SecurityGroupIngress": [{
                     "CidrIp": "0.0.0.0/0",
                     "IpProtocol": "tcp",
                     "FromPort": "80",
                     "ToPort": "80"
                 }],
                 "Tags": [{
                     "Key": "Name",
                     "Value": "PublicHTTPSecurityGroup"
                 }]
             })),
         Resource(
             "SSHBastionSecurityGroup", "AWS::EC2::SecurityGroup",
             Properties({
                 "VpcId": {
                     "Ref": "VPC"
                 },
                 "GroupDescription":
                 "Ingress for SSH from anywhere",
                 "SecurityGroupIngress": [{
                     "IpProtocol": "tcp",
                     "FromPort": "22",
                     "ToPort": "22",
                     "CidrIp": "0.0.0.0/0"
                 }],
                 "Tags": [{
                     "Key": "Name",
                     "Value": "SSHBastionSecurityGroup"
                 }]
             })),
         Resource(
             "SSHFromBastionSecurityGroup", "AWS::EC2::SecurityGroup",
             Properties({
                 "VpcId": {
                     "Ref": "VPC"
                 },
                 "GroupDescription":
                 "SSH from SSH Bastion SecurityGroup",
                 "SecurityGroupIngress": [{
                     "IpProtocol": "tcp",
                     "FromPort": "22",
                     "ToPort": "22",
                     "SourceSecurityGroupId": {
                         "Ref": "SSHBastionSecurityGroup"
                     }
                 }],
                 "Tags": [{
                     "Key": "Name",
                     "Value": "SSHFromBastionSecurityGroup"
                 }]
             })),
         Resource(
             "SQSUser", "AWS::IAM::User",
             Properties({
                 "Policies": [{
                     "PolicyName": "AmazonSQSFullAccess",
                     "PolicyDocument": {
                         "Version":
                         "2012-10-17",
                         "Statement": [{
                             "Effect": "Allow",
                             "Action": ["sqs:*"],
                             "Resource": "*"
                         }]
                     }
                 }]
             })),
         Resource("SQSAccessKey", "AWS::IAM::AccessKey",
                  Properties({"UserName": {
                      "Ref": "SQSUser"
                  }}))
     ]
    def _get_coreos_resources(self):
        resources = self._get_autoscale(
            'CoreOS',
            extra_security_groups=[
                'CoreOSSecurityGroup', 'WebAppSecurityGroup'
            ],
            extra_cloud_config=[
                "coreos:\n", "  etcd2:\n", "    discovery: ", {
                    "Ref": "DiscoveryURL"
                }, "\n", "    proxy: on\n",
                "    listen-client-urls: http://0.0.0.0:2379\n"
                "  fleet:\n", "    metadata: \"role=worker\"\n",
                "    etcd_servers: http://127.0.0.1:2379\n", "  flannel:\n",
                "    etcd_endpoints: http://127.0.0.1:2379\n", "  units:\n",
                "    - name: etcd2.service\n", "      command: start\n",
                "    - name: fleet.service\n", "      command: start\n",
                "    - name: flanneld.service\n", "      drop-ins:\n",
                "      - name: 50-network-config.conf\n",
                "        content: |\n", "          [Unit]\n",
                "          Requires=etcd2.service\n", "          [Service]\n",
                "          ExecStartPre=/usr/bin/etcdctl set /coreos.com/network/config '{ \"Network\": \"192.168.192.0/18\", \"Backend\": {\"Type\": \"vxlan\"}}'\n",
                "      command: start\n"
            ],
            config_min_size=1,
            config_max_size=12,
            extra_props_autoscale={
                "VPCZoneIdentifier": [{
                    "Ref": subnet_name
                } for subnet_name in self.data['private_subnets']],
                "DesiredCapacity": {
                    "Ref": "CoreOSClusterSize"
                }
            })

        resources.append(
            Resource(
                "WebAppSecurityGroup", "AWS::EC2::SecurityGroup",
                Properties({
                    "VpcId": {
                        "Ref": "VPC"
                    },
                    "GroupDescription":
                    "WebApp SecurityGroup",
                    "SecurityGroupIngress": [{
                        "IpProtocol": "tcp",
                        "FromPort": "8080",
                        "ToPort": "8080",
                        "SourceSecurityGroupId": {
                            "Ref": "NATSecurityGroup"
                        }
                    }, {
                        "IpProtocol": "tcp",
                        "FromPort": "8080",
                        "ToPort": "8080",
                        "SourceSecurityGroupId": {
                            "Ref": "PublicHTTPSecurityGroup"
                        }
                    }],
                    "Tags": [{
                        "Key": "Name",
                        "Value": "WebAppSecurityGroup"
                    }]
                })))
        return resources
 def _get_resources(self):
     return [
         Resource(
             "NATSecurityGroup", "AWS::EC2::SecurityGroup",
             Properties({
                 "VpcId": {
                     "Ref": "VPC"
                 },
                 "GroupDescription":
                 "NAT Instance Security Group",
                 "SecurityGroupIngress": [{
                     "IpProtocol": "icmp",
                     "FromPort": "-1",
                     "ToPort": "-1",
                     "CidrIp": "10.0.0.0/16"
                 }, {
                     "IpProtocol": "tcp",
                     "FromPort": "0",
                     "ToPort": "65535",
                     "CidrIp": "10.0.0.0/16"
                 }],
                 "Tags": [{
                     "Key": "Name",
                     "Value": "NATSecurityGroup"
                 }]
             })),
         Resource("NATInstance",
                  "AWS::EC2::Instance",
                  Properties({
                      "ImageId": {
                          "Fn::FindInMap":
                          ["RegionMap", {
                              "Ref": "AWS::Region"
                          }, "nat"]
                      },
                      "InstanceType": {
                          "Ref": "NATInstanceType"
                      },
                      "BlockDeviceMappings": [{
                          "DeviceName": "/dev/xvda",
                          "Ebs": {
                              "VolumeSize": 10
                          }
                      }],
                      "NetworkInterfaces": [{
                          "GroupSet": [{
                              "Ref": "NATSecurityGroup"
                          }, {
                              "Ref": "SSHFromBastionSecurityGroup"
                          }],
                          "SubnetId": {
                              "Ref": self.data['public_subnets'][0]
                          },
                          "AssociatePublicIpAddress":
                          "true",
                          "DeviceIndex":
                          "0",
                          "DeleteOnTermination":
                          "true"
                      }],
                      "SourceDestCheck":
                      "false",
                      "Tags": [{
                          "Key": "Name",
                          "Value": "NATHost"
                      }, {
                          "Key": "Role",
                          "Value": "NAT"
                      }],
                      "UserData": {
                          "Fn::Base64": {
                              "Fn::Join":
                              ["", self.get_user_cloud_config()]
                          }
                      }
                  }),
                  attributes=[DependsOn("GatewayToInternet")])
     ]
    def _get_private_subnets(self):
        resources = [
            Resource(
                "PrivateRouteTable", "AWS::EC2::RouteTable",
                Properties({
                    "VpcId": {
                        "Ref": "VPC"
                    },
                    "Tags": [{
                        "Key": "Name",
                        "Value": "PrivateRouteTable"
                    }]
                })),
            Resource("PrivateInternetRoute",
                     "AWS::EC2::Route",
                     Properties({
                         "RouteTableId": {
                             "Ref": "PrivateRouteTable"
                         },
                         "DestinationCidrBlock": "0.0.0.0/0",
                         "InstanceId": {
                             "Ref": "NATInstance"
                         }
                     }),
                     attributes=[DependsOn("NATInstance")]),
        ]

        for subnet_name in self.data['private_subnets']:
            table_association_name = "%sRouteTableAssociation" % subnet_name

            resources += [
                Resource(
                    subnet_name, "AWS::EC2::Subnet",
                    Properties({
                        "VpcId": {
                            "Ref": "VPC"
                        },
                        "AvailabilityZone": {
                            "Fn::FindInMap":
                            ["SubnetConfig", subnet_name, "AZ"]
                        },
                        "CidrBlock": {
                            "Fn::FindInMap":
                            ["SubnetConfig", subnet_name, "CIDR"]
                        },
                        "Tags": [{
                            "Key": "Application",
                            "Value": {
                                "Ref": "AWS::StackId"
                            }
                        }, {
                            "Key": "Network",
                            "Value": subnet_name
                        }]
                    })),
                Resource(
                    table_association_name,
                    "AWS::EC2::SubnetRouteTableAssociation",
                    Properties({
                        "SubnetId": {
                            "Ref": subnet_name
                        },
                        "RouteTableId": {
                            "Ref": "PrivateRouteTable"
                        }
                    })),
            ]
        return resources
    def _get_autoscale(self,
                       name,
                       extra_security_groups=[],
                       extra_cloud_config='',
                       extra_props_autoscale={},
                       extra_props_launch={},
                       extra_attrs_launch=[],
                       config_min_size=3,
                       config_max_size=3):

        # general configs
        autoscale_name = '%sServerAutoScale' % name
        autoscale_launch_config = '%sServerLaunchConfig' % name

        # autoscaling configs
        props_autoscale = {
            "AvailabilityZones": {
                "Fn::GetAZs": {
                    "Ref": "AWS::Region"
                }
            },
            "LaunchConfigurationName": {
                "Ref": autoscale_launch_config
            },
            "MinSize":
            "%s" % config_min_size,
            "MaxSize":
            "%s" % config_max_size,
            "Tags": [{
                "Key": "Name",
                "Value": name,
                "PropagateAtLaunch": True
            }, {
                "Key": "Role",
                "Value": name,
                "PropagateAtLaunch": True
            }]
        }

        props_autoscale.update(extra_props_autoscale)

        # launch configs
        sec_groups = [{
            "Ref": sec_group
        } for sec_group in ["SSHFromBastionSecurityGroup"] +
                      extra_security_groups]

        cloud_config = self.get_user_cloud_config()
        cloud_config += extra_cloud_config

        props_launch = {
            "ImageId": {
                "Fn::FindInMap": ["RegionMap", {
                    "Ref": "AWS::Region"
                }, name]
            },
            "InstanceType": {
                "Ref": "%sInstanceType" % name
            },
            "SecurityGroups": sec_groups,
            "UserData": {
                "Fn::Base64": join('', *cloud_config)
            }
        }
        props_launch.update(extra_props_launch)

        attrs_launch = extra_attrs_launch

        return [
            Resource(autoscale_name, "AWS::AutoScaling::AutoScalingGroup",
                     Properties(props_autoscale)),
            Resource(autoscale_launch_config,
                     "AWS::AutoScaling::LaunchConfiguration",
                     Properties(props_launch),
                     attributes=attrs_launch)
        ]
Example #14
0
def make_storage_template():
    cft = CloudFormationTemplate(description="Refinery Platform storage")

    # Parameters
    cft.parameters.add(
        Parameter('StaticBucketName', 'String', {
            'Description': 'Name of S3 bucket for Django static files',
        }))
    cft.parameters.add(
        Parameter(
            'MediaBucketName',
            'String',
            {
                'Description':
                'Name of S3 bucket for Django media files',
                # make names DNS-compliant without periods (".") for
                # compatibility with virtual-hosted-style access and S3
                # Transfer Acceleration
                'AllowedPattern':
                '[a-z0-9\-]+',
                'ConstraintDescription':
                'must only contain lower case letters, numbers, and '
                'hyphens',
            }))
    cft.parameters.add(
        Parameter(
            'IdentityPoolName', 'String', {
                'Default': 'Refinery Platform',
                'Description': 'Name of Cognito identity pool for S3 uploads',
            }))
    cft.parameters.add(
        Parameter(
            'DeveloperProviderName', 'String', {
                'Default':
                'login.refinery',
                'Description':
                '"domain" by which Cognito will refer to users',
                'AllowedPattern':
                '[a-z\-\.]+',
                'ConstraintDescription':
                'must only contain lower case letters, periods, '
                'underscores, and hyphens'
            }))

    # Resources
    cft.resources.add(
        Resource(
            'StaticStorageBucket',
            'AWS::S3::Bucket',
            Properties({
                'BucketName': ref('StaticBucketName'),
                'AccessControl': 'PublicRead',
                'CorsConfiguration': {
                    'CorsRules': [{
                        'AllowedOrigins': ['*'],
                        'AllowedMethods': ['GET'],
                        'AllowedHeaders': ['Authorization'],
                        'MaxAge': 3000,
                    }]
                },
            }),
            DeletionPolicy('Retain'),
        ))
    cft.resources.add(
        Resource(
            'MediaStorageBucket',
            'AWS::S3::Bucket',
            Properties({
                'BucketName': ref('MediaBucketName'),
                'AccessControl': 'PublicRead',
                'CorsConfiguration': {
                    'CorsRules': [{
                        'AllowedOrigins': ['*'],
                        'AllowedMethods': ['POST', 'PUT', 'DELETE'],
                        'AllowedHeaders': ['*'],
                        'ExposedHeaders': ['ETag'],
                        'MaxAge': 3000,
                    }]
                }
            }),
            DeletionPolicy('Retain'),
        ))
    # Cognito Identity Pool for Developer Authenticated Identities Authflow
    # http://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html
    cft.resources.add(
        Resource(
            'IdentityPool', 'AWS::Cognito::IdentityPool',
            Properties({
                'IdentityPoolName': ref('IdentityPoolName'),
                'AllowUnauthenticatedIdentities': False,
                'DeveloperProviderName': ref('DeveloperProviderName'),
            })))
    cft.resources.add(
        Resource(
            'IdentityPoolAuthenticatedRole',
            'AWS::Cognito::IdentityPoolRoleAttachment',
            Properties({
                'IdentityPoolId': ref('IdentityPool'),
                'Roles': {
                    'authenticated': get_att('CognitoS3UploadRole', 'Arn'),
                }
            })))
    upload_role_trust_policy = {
        "Version":
        "2012-10-17",
        "Statement": [{
            "Effect": "Allow",
            "Principal": {
                "Federated": "cognito-identity.amazonaws.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "cognito-identity.amazonaws.com:aud": ref('IdentityPool')
                },
                "ForAnyValue:StringLike": {
                    "cognito-identity.amazonaws.com:amr": "authenticated"
                }
            }
        }]
    }
    upload_access_policy = {
        "Version":
        "2012-10-17",
        "Statement": [{
            "Effect": "Allow",
            "Action": ["cognito-identity:*"],
            "Resource": "*"
        }, {
            "Action": ["s3:PutObject", "s3:AbortMultipartUpload"],
            "Effect": "Allow",
            "Resource": {
                "Fn::Sub":
                "arn:aws:s3:::${MediaStorageBucket}/uploads/"
                "${!cognito-identity.amazonaws.com:sub}/*"
            }
        }]
    }
    cft.resources.add(
        Resource(
            'CognitoS3UploadRole', 'AWS::IAM::Role',
            Properties({
                'AssumeRolePolicyDocument':
                upload_role_trust_policy,
                'Policies': [{
                    'PolicyName': 'AuthenticatedS3UploadPolicy',
                    'PolicyDocument': upload_access_policy,
                }]
            })))

    # Outputs
    cft.outputs.add(
        Output('IdentityPoolId', ref('IdentityPool'),
               {'Fn::Sub': '${AWS::StackName}IdentityPoolId'},
               'Cognito identity pool ID'))

    return cft
 def _get_resources(self):
     return [
         Resource(
             "MasterDBSubnetGroup", "AWS::RDS::DBSubnetGroup",
             Properties({
                 "DBSubnetGroupDescription":
                 "Master DB subnet group",
                 "SubnetIds": [{
                     "Ref": subnet_name
                 } for subnet_name in self.data['private_subnets']]
             })),
         Resource(
             "MasterDBSecurityGroup", "AWS::EC2::SecurityGroup",
             Properties({
                 "VpcId": {
                     "Ref": "VPC"
                 },
                 "GroupDescription":
                 "Ingress for CoreOS instance security group",
                 "SecurityGroupIngress": [{
                     "SourceSecurityGroupId": {
                         "Ref": "CoreOSSecurityGroup"
                     },
                     "IpProtocol": "tcp",
                     "FromPort": "5432",
                     "ToPort": "5432"
                 }],
                 "Tags": [{
                     "Key": "Name",
                     "Value": "MasterDBSecurityGroup"
                 }]
             })),
         Resource(
             "PrimaryDB", "AWS::RDS::DBInstance",
             Properties({
                 "DBName": {
                     "Ref": "DBName"
                 },
                 "AllocatedStorage": {
                     "Ref": "DBAllocatedStorage"
                 },
                 "DBInstanceClass": {
                     "Ref": "DBInstanceClass"
                 },
                 "Engine":
                 "postgres",
                 "EngineVersion":
                 "9.3.5",
                 "MasterUsername": {
                     "Ref": "DBUsername"
                 },
                 "MasterUserPassword": {
                     "Ref": "DBPassword"
                 },
                 "Port":
                 "5432",
                 "VPCSecurityGroups": [{
                     "Ref": "MasterDBSecurityGroup"
                 }],
                 "PubliclyAccessible":
                 "false",
                 "PreferredMaintenanceWindow":
                 "sun:12:00-sun:12:30",
                 "PreferredBackupWindow":
                 "23:00-23:30",
                 "BackupRetentionPeriod":
                 "7",
                 "DBParameterGroupName":
                 "default.postgres9.3",
                 "AutoMinorVersionUpgrade":
                 "true",
                 "MultiAZ":
                 "false",
                 "DBSubnetGroupName": {
                     "Ref": "MasterDBSubnetGroup"
                 },
                 "Tags": [{
                     "Key": "Role",
                     "Value": "Primary"
                 }]
             }))
     ]
Example #16
0
def resolve_host(hostname):
    ips = dns.resolver.query(hostname, "A")
    # sort these so that we deterministically set up the same route
    # resources (until DNS changes)
    ips = sorted([i.to_text() for i in ips])
    return ips

# VPC

cft = CloudFormationTemplate(description="Release Engineering network configuration")

cft.resources.add(Resource(
    'RelengVPC', 'AWS::EC2::VPC',
    Properties({
        'CidrBlock': subnet_cidr('0.0', 16),
        'Tags': [nametag('Releng Network')],
    })
))

# DHCP options

cft.resources.add(Resource(
    'DHCPOptions', 'AWS::EC2::DHCPOptions',
    Properties({
        # point to the onsite, IT-managed DNS servers
        'DomainNameServers': [
            "10.26.75.40",
            "10.26.75.41"
        ],
        'Tags': [nametag('Releng Network Options')],
from cfn_pyplates.core import Properties, options
from utils import nametag
from utils import sgcidr

cft = CloudFormationTemplate(description="IT Resources")

cft.resources.add(Resource(
    'NagiosSG', 'AWS::EC2::SecurityGroup',
    Properties({
        'GroupDescription': 'Nagios Servers',
        'Tags': [nametag('nagios')],
        'VpcId': options['vpcid'],
        'SecurityGroupIngress': [
            sgcidr('10.22.8.128/32', -1, -1),
            sgcidr('10.22.20.0/25', -1, -1),
            sgcidr('10.22.72.136/32', -1, -1),
            sgcidr('10.22.72.155/32', -1, -1),
            sgcidr('10.22.72.158/32', -1, -1),
            sgcidr('10.22.72.159/32', -1, -1),
            sgcidr('10.22.75.5/32', -1, -1),
            sgcidr('10.22.75.6/31', -1, -1),
            sgcidr('10.22.240.0/20', -1, -1),
            sgcidr('10.22.74.22/32', -1, -1),
            sgcidr('10.22.75.30/32', -1, -1),
            sgcidr('10.22.75.36/32', 'tcp', 22),
            sgcidr('10.22.75.136/32', 'udp', 161),
            sgcidr('0.0.0.0/0', 'icmp', -1),
        ],
    }),
))