Beispiel #1
0
def test_create_instance():
    aws_env = AWSEnv(regions=['us-east-1'], stub=True)
    with default_region('us-east-1'):
        stub = aws_env.stub('ec2', region='us-east-1')
        stub.add_response(
            'describe_images',
            {'Images': [{'ImageId': 'ami-1234',
                         'RootDeviceName': '/dev/sda1'}]},
            {'ImageIds': ANY})

        i = Instance('testmachine', AMI('ami-1234'), disk_size=20)
        assert i.properties

        i.add(EphemeralDisk('/dev/sdb', 0))
        assert i.properties

        vpc = VPC('VPC', '10.10.0.0/16')
        subnet = Subnet('Subnet', vpc, '10.10.10.0/24')
        subnet = Subnet('Subnet2', vpc, '10.10.20.0/24')
        security_group = SecurityGroup('mysgroup', vpc)
        i.add(NetworkInterface(subnet, description='first network interface'))
        i.add(NetworkInterface(subnet,
                               groups=[security_group],
                               description='2nd network interface'))
        i.add(NetworkInterface(subnet,
                               groups=[security_group],
                               description='3rd network interface',
                               device_index=3))
        assert i.properties

        with pytest.raises(AssertionError):
            i.add("non valid ec2 device")
Beispiel #2
0
    def add_private_server(self, server_ami, names,
                           instance_type='t2.micro',
                           disk_size=20,
                           amazon_access=True):
        """Add servers in the private network.

        :param server_ami: AMI to use
        :type server_ami: AMI
        :param names: list of server names (names will be used as stack logical
            names)
        :type names: list[str]
        :param instance_type: instance type (default: t2.micro)
        :type instance_type: str
        :param disk_size: disk size of the instance in Go
        :type disk_size: int
        :param amazon_access: if True add a security group that allow access to
            amazon services. Default is True
        :type amazon_access: bool
        """
        groups = [self[self.name + 'InternalSG']]
        if amazon_access:
            groups.append(self[self.name + 'AmazonServices'])

        for name in names:
            self.add(Instance(name, server_ami,
                              instance_type=instance_type,
                              disk_size=disk_size))
            self[name].add(
                NetworkInterface(self.private_subnet.subnet,
                                 public_ip=False,
                                 groups=groups))
            self[name].set_instance_profile(
                self[self.name + 'PrivServerInstanceRole'].instance_profile)
            self[name].tags['Name'] = '%s (%s)' % (name, self.name)
Beispiel #3
0
    def add_private_server(self,
                           server_ami,
                           names,
                           instance_type='t2.micro',
                           disk_size=20,
                           amazon_access=True,
                           persistent_eni=False):
        """Add servers in the private network.

        :param server_ami: AMI to use
        :type server_ami: AMI
        :param names: list of server names (names will be used as stack logical
            names)
        :type names: list[str]
        :param instance_type: instance type (default: t2.micro)
        :type instance_type: str
        :param disk_size: disk size of the instance in Go
        :type disk_size: int
        :param amazon_access: if True add a security group that allow access to
            amazon services. Default is True
        :type amazon_access: bool
        :param persistent_eni: Use a separate network interface (i.e: not
            embedded inside the EC2 instance). This is useful to preserve for
            example IP address and MAC address when a server is redeployed.
        :type persistent_eni: bool
        """
        groups = [self[self.name + 'InternalSG']]
        if amazon_access:
            groups.append(self[self.name + 'AmazonServices'])

        for name in names:
            self.add(
                Instance(name,
                         server_ami,
                         instance_type=instance_type,
                         disk_size=disk_size))
            if not persistent_eni:
                self[name].add(
                    EC2NetworkInterface(self.private_subnet.subnet,
                                        public_ip=False,
                                        groups=groups))
            else:
                network_interface = NetworkInterface(
                    name + 'ENI',
                    subnet=self.private_subnet.subnet,
                    groups=groups)
                self.add(network_interface)
                self[name].add(
                    EC2NetworkInterface(interface=network_interface))

            self[name].set_instance_profile(
                self[self.name + 'PrivServerInstanceRole'].instance_profile)
            self[name].tags['Name'] = '%s (%s)' % (name, self.name)
Beispiel #4
0
    def __init__(self,
                 name,
                 internal_server_policy,
                 bastion_ami=None,
                 allow_ssh_from=None,
                 description=None,
                 vpc_cidr_block='10.10.0.0/16',
                 private_cidr_block='10.10.0.0/17',
                 public_cidr_block='10.10.128.0/17'):
        """Create a VPC Fortress.

        This create a vpc with a public and a private subnet. Servers in the
        private subnet are only accessible through a bastion machine declare
        in the public subnet.

        :param name: stack name
        :type name: str
        :param internal_server_policy: policy associated with instance role
            of private servers
        :type internal_server_policy: Policy
        :param bastion_ami: AMI used for the bastion server. If None no bastion
            is setup
        :type bastion_ami: AMI | None
        :param allow_ssh_from: ip ranges from which ssh can be done to the
            bastion. if bastion_ami is None, parameter is discarded
        :type allow_ssh_from: str | None
        :param vpc_cidr_block: ip ranges for the associated vpc
        :type vpc_cidr_block: str
        :param private_cidr_block: ip ranges (subset of vpc_cidr_block) used
            for private subnet
        :type private_cidr_block: str
        :param public_cidr_block: ip ranges (subset of vpc_cidr_block) used
            for public subnet
        :type public_cidr_block: str
        """
        super(Fortress, self).__init__(name, description)

        # Create VPC along with the two subnets
        self.add(VPCStack(self.name + 'VPC', vpc_cidr_block))
        self.vpc.add_subnet(self.name + 'PublicNet', public_cidr_block,
                            is_public=True, use_nat=True)
        self.vpc.add_subnet(self.name + 'PrivateNet', private_cidr_block,
                            nat_to=self.name + 'PublicNet')

        self.add(amazon_security_group(self.name + 'AmazonServices',
                                       self.vpc.vpc))

        if bastion_ami is not None:
            # Allow ssh to bastion only from a range of IP address
            self.add(SecurityGroup(
                self.name + 'BastionSG',
                self.vpc.vpc,
                description='security group for bastion servers',
                rules=[Ipv4IngressRule('ssh', cidr)
                       for cidr in allow_ssh_from]))

            # Create the bastion
            self.add(Instance(self.name + 'Bastion', bastion_ami))
            self.bastion.tags['Name'] = 'Bastion (%s)' % self.name
            self.bastion.add(
                NetworkInterface(self.public_subnet.subnet,
                                 public_ip=True,
                                 groups=[self[self.name + 'BastionSG']]))

            # Create security group for internal servers
            self.add(SecurityGroup(
                self.name + 'InternalSG',
                self.vpc.vpc,
                description='Allow ssh inside VPC',
                rules=[Ipv4IngressRule('ssh', self.public_subnet.cidr_block)]))
        else:
            # If no bastion is used do not authorize ssh inside the vpc
            self.add(SecurityGroup(
                self.name + 'InternalSG',
                self.vpc.vpc,
                description='Do not allow ssh inside VPC'))

        ir = InstanceRole(self.name + 'PrivServerInstanceRole')
        ir.add_policy(internal_server_policy)
        self.add(ir)
Beispiel #5
0
    def add_private_server(
        self,
        server_ami,
        names,
        instance_type="t2.micro",
        disk_size=None,
        amazon_access=True,
        github_access=False,
        persistent_eni=False,
        is_template=False,
        template_name=None,
        extra_groups=None,
    ):
        """Add servers in the private network.

        :param server_ami: AMI to use
        :type server_ami: AMI
        :param names: list of server names (names will be used as stack logical
            names)
        :type names: list[str]
        :param instance_type: instance type (default: t2.micro)
        :type instance_type: str
        :param disk_size: disk size of the instance in Go or None to reuse the
            AMI snapshot size
        :type disk_size: int | None
        :param amazon_access: if True add a security group that allow access to
            amazon services. Default is True
        :type amazon_access: bool
        :param github_access: if True add a security group that allow access to
            github services. Default is False
        :type github_access: bool
        :param persistent_eni: Use a separate network interface (i.e: not
            embedded inside the EC2 instance). This is useful to preserve for
            example IP address and MAC address when a server is redeployed.
        :type persistent_eni: bool
        :param is_template: create a template rather than an instance
        :type is_template: bool
        :param extra_groups: a list of security groups to add
        :type extra_groups: Optional[List[SecurityGroup]]
        """
        groups = self.private_server_security_groups(
            amazon_access=amazon_access,
            github_access=github_access,
            extra_groups=extra_groups,
        )

        for name in names:
            if not is_template:
                self.add(
                    Instance(
                        name,
                        server_ami,
                        instance_type=instance_type,
                        disk_size=disk_size,
                    ))
            else:
                self.add(
                    LaunchTemplate(
                        name,
                        server_ami,
                        instance_type=instance_type,
                        disk_size=disk_size,
                        template_name=template_name,
                    ))

            if not persistent_eni:
                self[name].add(
                    EC2NetworkInterface(self.private_subnet.subnet,
                                        public_ip=False,
                                        groups=groups))
            else:
                network_interface = NetworkInterface(
                    name + "ENI",
                    subnet=self.private_subnet.subnet,
                    groups=groups)
                self.add(network_interface)
                self[name].add(
                    EC2NetworkInterface(interface=network_interface))

            self[name].set_instance_profile(
                self[self.name + "PrivServerInstanceRole"].instance_profile)
            self[name].tags["Name"] = "%s (%s)" % (name, self.name)