2014-07-23 17:43:28 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
# import Python Libs
|
2014-11-21 19:05:13 +00:00
|
|
|
from __future__ import absolute_import
|
2014-08-04 00:04:20 +00:00
|
|
|
import random
|
|
|
|
import string
|
2014-08-05 03:45:00 +00:00
|
|
|
from copy import deepcopy
|
2014-11-28 15:31:01 +00:00
|
|
|
from distutils.version import LooseVersion # pylint: disable=import-error,no-name-in-module
|
2014-07-23 17:43:28 +00:00
|
|
|
|
2014-11-22 12:15:11 +00:00
|
|
|
# Import Salt Testing Libs
|
|
|
|
from salttesting.unit import skipIf, TestCase
|
|
|
|
from salttesting.mock import NO_MOCK, NO_MOCK_REASON
|
|
|
|
from salttesting.helpers import ensure_in_syspath
|
|
|
|
|
|
|
|
ensure_in_syspath('../../')
|
|
|
|
|
2015-04-13 22:04:00 +00:00
|
|
|
# Import Salt libs
|
|
|
|
import salt.config
|
|
|
|
import salt.loader
|
|
|
|
|
2014-11-22 12:15:11 +00:00
|
|
|
# Import Third Party Libs
|
2014-11-28 15:31:01 +00:00
|
|
|
# pylint: disable=import-error
|
2014-11-22 12:15:11 +00:00
|
|
|
from salt.ext.six.moves import range # pylint: disable=redefined-builtin
|
2014-08-04 00:04:20 +00:00
|
|
|
try:
|
|
|
|
import boto
|
2014-08-11 21:25:21 +00:00
|
|
|
HAS_BOTO = True
|
2014-08-11 18:57:45 +00:00
|
|
|
except ImportError:
|
|
|
|
HAS_BOTO = False
|
|
|
|
|
|
|
|
try:
|
2014-08-04 00:04:20 +00:00
|
|
|
from moto import mock_ec2
|
2014-08-11 21:25:21 +00:00
|
|
|
HAS_MOTO = True
|
2014-08-04 00:04:20 +00:00
|
|
|
except ImportError:
|
2014-08-11 18:57:45 +00:00
|
|
|
HAS_MOTO = False
|
2014-08-04 00:04:20 +00:00
|
|
|
|
|
|
|
def mock_ec2(self):
|
|
|
|
'''
|
|
|
|
if the mock_ec2 function is not available due to import failure
|
|
|
|
this replaces the decorated function with stub_function.
|
|
|
|
Allows boto_secgroup unit tests to use the @mock_ec2 decorator
|
|
|
|
without a "NameError: name 'mock_ec2' is not defined" error.
|
|
|
|
'''
|
|
|
|
def stub_function(self):
|
|
|
|
pass
|
|
|
|
return stub_function
|
2015-02-21 07:44:01 +00:00
|
|
|
# pylint: enable=import-error
|
2014-08-04 00:04:20 +00:00
|
|
|
|
2014-07-23 17:43:28 +00:00
|
|
|
# Import Salt Libs
|
2014-08-20 15:24:52 +00:00
|
|
|
from salt.utils.odict import OrderedDict
|
2014-07-23 17:43:28 +00:00
|
|
|
from salt.modules import boto_secgroup
|
|
|
|
|
2014-08-04 00:04:20 +00:00
|
|
|
|
2014-08-15 22:57:44 +00:00
|
|
|
required_boto_version = '2.4.0'
|
2014-08-04 00:04:20 +00:00
|
|
|
vpc_id = 'vpc-mjm05d27'
|
|
|
|
region = 'us-east-1'
|
|
|
|
access_key = 'GKTADJGHEIQSXMKKRBJ08H'
|
|
|
|
secret_key = 'askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs'
|
|
|
|
conn_parameters = {'region': region, 'key': access_key, 'keyid': secret_key, 'profile': {}}
|
2014-08-15 01:12:43 +00:00
|
|
|
boto_conn_parameters = {'aws_access_key_id': access_key, 'aws_secret_access_key': secret_key}
|
2014-08-04 00:04:20 +00:00
|
|
|
|
2015-04-13 22:04:00 +00:00
|
|
|
opts = salt.config.DEFAULT_MASTER_OPTS
|
|
|
|
utils = salt.loader.utils(opts, whitelist=['boto'])
|
2016-02-09 18:52:15 +00:00
|
|
|
funcs = salt.loader.minion_mods(opts, utils=utils)
|
|
|
|
boto_secgroup.__salt__ = funcs
|
2015-04-13 22:04:00 +00:00
|
|
|
boto_secgroup.__utils__ = utils
|
|
|
|
boto_secgroup.__virtual__()
|
|
|
|
|
2014-08-04 00:04:20 +00:00
|
|
|
|
2014-08-05 03:45:00 +00:00
|
|
|
def _random_group_id():
|
|
|
|
group_id = 'sg-{0:x}'.format(random.randrange(2 ** 32))
|
|
|
|
return group_id
|
|
|
|
|
|
|
|
|
2014-08-04 00:04:20 +00:00
|
|
|
def _random_group_name():
|
|
|
|
group_name = 'boto_secgroup-{0}'.format(''.join((random.choice(string.ascii_lowercase)) for char in range(12)))
|
|
|
|
return group_name
|
2014-07-23 17:43:28 +00:00
|
|
|
|
|
|
|
|
2014-08-15 22:57:44 +00:00
|
|
|
def _has_required_boto():
|
2014-08-15 18:58:26 +00:00
|
|
|
'''
|
2014-08-15 22:57:44 +00:00
|
|
|
Returns True/False boolean depending on if Boto is installed and correct
|
|
|
|
version.
|
2014-08-15 18:58:26 +00:00
|
|
|
'''
|
2014-08-15 22:57:44 +00:00
|
|
|
if not HAS_BOTO:
|
|
|
|
return False
|
2014-08-15 23:05:05 +00:00
|
|
|
elif LooseVersion(boto.__version__) < LooseVersion(required_boto_version):
|
2014-08-15 22:57:44 +00:00
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
2014-08-15 18:58:26 +00:00
|
|
|
|
|
|
|
|
2014-08-11 18:57:45 +00:00
|
|
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
|
|
|
@skipIf(HAS_BOTO is False, 'The boto module must be installed.')
|
|
|
|
@skipIf(HAS_MOTO is False, 'The moto module must be installed.')
|
2014-08-15 22:57:44 +00:00
|
|
|
@skipIf(_has_required_boto() is False, 'The boto module must be greater than'
|
|
|
|
' or equal to version {0}'
|
|
|
|
.format(required_boto_version))
|
2014-08-12 22:57:34 +00:00
|
|
|
class BotoSecgroupTestCase(TestCase):
|
2014-07-23 17:43:28 +00:00
|
|
|
'''
|
|
|
|
TestCase for salt.modules.boto_secgroup module
|
|
|
|
'''
|
2014-08-12 15:20:17 +00:00
|
|
|
|
2014-07-23 17:43:28 +00:00
|
|
|
def test__split_rules(self):
|
|
|
|
'''
|
|
|
|
tests the splitting of a list of rules into individual rules
|
|
|
|
'''
|
|
|
|
rules = [OrderedDict([('ip_protocol', u'tcp'), ('from_port', 22), ('to_port', 22), ('grants', [OrderedDict([('cidr_ip', u'0.0.0.0/0')])])]),
|
|
|
|
OrderedDict([('ip_protocol', u'tcp'), ('from_port', 80), ('to_port', 80), ('grants', [OrderedDict([('cidr_ip', u'0.0.0.0/0')])])])]
|
|
|
|
split_rules = [{'to_port': 22, 'from_port': 22, 'ip_protocol': u'tcp', 'cidr_ip': u'0.0.0.0/0'},
|
|
|
|
{'to_port': 80, 'from_port': 80, 'ip_protocol': u'tcp', 'cidr_ip': u'0.0.0.0/0'}]
|
|
|
|
self.assertEqual(boto_secgroup._split_rules(rules), split_rules)
|
|
|
|
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test_create_ec2_classic(self):
|
|
|
|
'''
|
2014-10-10 22:03:21 +00:00
|
|
|
Test of creation of an EC2-Classic security group. The test ensures
|
2014-08-05 03:45:00 +00:00
|
|
|
that a group was created with the desired name and description
|
|
|
|
'''
|
|
|
|
group_name = _random_group_name()
|
|
|
|
group_description = 'test_create_ec2_classic'
|
|
|
|
boto_secgroup.create(group_name, group_description, **conn_parameters)
|
2014-08-15 01:12:43 +00:00
|
|
|
conn = boto.ec2.connect_to_region(region, **boto_conn_parameters)
|
2014-10-10 22:03:21 +00:00
|
|
|
group_filter = {'group-name': group_name}
|
2014-08-05 03:45:00 +00:00
|
|
|
secgroup_created_group = conn.get_all_security_groups(filters=group_filter)
|
2014-10-10 22:03:21 +00:00
|
|
|
expected_create_result = [group_name,
|
|
|
|
group_description,
|
|
|
|
None]
|
|
|
|
secgroup_create_result = [secgroup_created_group[0].name,
|
|
|
|
secgroup_created_group[0].description,
|
|
|
|
secgroup_created_group[0].vpc_id]
|
2014-08-05 03:45:00 +00:00
|
|
|
self.assertEqual(expected_create_result, secgroup_create_result)
|
|
|
|
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test_create_ec2_vpc(self):
|
|
|
|
'''
|
|
|
|
test of creation of an EC2-VPC security group. The test ensures that a
|
|
|
|
group was created in a given vpc with the desired name and description
|
|
|
|
'''
|
|
|
|
group_name = _random_group_name()
|
|
|
|
group_description = 'test_create_ec2_vpc'
|
|
|
|
# create a group using boto_secgroup
|
|
|
|
boto_secgroup.create(group_name, group_description, vpc_id=vpc_id, **conn_parameters)
|
|
|
|
# confirm that the group actually exists
|
2014-08-15 01:12:43 +00:00
|
|
|
conn = boto.ec2.connect_to_region(region, **boto_conn_parameters)
|
2014-08-05 03:45:00 +00:00
|
|
|
group_filter = {'group-name': group_name, 'vpc-id': vpc_id}
|
|
|
|
secgroup_created_group = conn.get_all_security_groups(filters=group_filter)
|
|
|
|
expected_create_result = [group_name, group_description, vpc_id]
|
|
|
|
secgroup_create_result = [secgroup_created_group[0].name, secgroup_created_group[0].description, secgroup_created_group[0].vpc_id]
|
|
|
|
self.assertEqual(expected_create_result, secgroup_create_result)
|
|
|
|
|
|
|
|
@skipIf(True, 'test skipped due to error in moto return - fixed in'
|
|
|
|
' https://github.com/spulec/moto/commit/cc0166964371f7b5247a49d45637a8f936ccbe6f')
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-04 00:04:20 +00:00
|
|
|
def test_get_group_id_ec2_classic(self):
|
|
|
|
'''
|
|
|
|
tests that given a name of a group in EC2-Classic that the correct
|
2014-08-11 18:52:30 +00:00
|
|
|
group id will be retrieved
|
2014-08-04 00:04:20 +00:00
|
|
|
'''
|
|
|
|
group_name = _random_group_name()
|
|
|
|
group_description = 'test_get_group_id_ec2_classic'
|
2014-08-15 01:12:43 +00:00
|
|
|
conn = boto.ec2.connect_to_region(region, **boto_conn_parameters)
|
2014-08-04 00:04:20 +00:00
|
|
|
group_classic = conn.create_security_group(name=group_name,
|
|
|
|
description=group_description)
|
|
|
|
# note that the vpc_id does not need to be created in order to create
|
|
|
|
# a security group within the vpc when using moto
|
|
|
|
group_vpc = conn.create_security_group(name=group_name,
|
|
|
|
description=group_description,
|
|
|
|
vpc_id=vpc_id)
|
2014-08-11 18:52:30 +00:00
|
|
|
retrieved_group_id = boto_secgroup.get_group_id(group_name,
|
2014-08-04 00:04:20 +00:00
|
|
|
**conn_parameters)
|
2014-08-11 18:52:30 +00:00
|
|
|
self.assertEqual(group_classic.id, retrieved_group_id)
|
2014-08-04 00:04:20 +00:00
|
|
|
|
|
|
|
@skipIf(True, 'test skipped because moto does not yet support group'
|
|
|
|
' filters https://github.com/spulec/moto/issues/154')
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-04 00:04:20 +00:00
|
|
|
def test_get_group_id_ec2_vpc(self):
|
|
|
|
'''
|
|
|
|
tests that given a name of a group in EC2-VPC that the correct
|
2014-08-11 18:52:30 +00:00
|
|
|
group id will be retrieved
|
2014-08-04 00:04:20 +00:00
|
|
|
'''
|
|
|
|
group_name = _random_group_name()
|
|
|
|
group_description = 'test_get_group_id_ec2_vpc'
|
2014-08-15 01:12:43 +00:00
|
|
|
conn = boto.ec2.connect_to_region(region, **boto_conn_parameters)
|
2014-08-04 00:04:20 +00:00
|
|
|
group_classic = conn.create_security_group(name=group_name,
|
|
|
|
description=group_description)
|
|
|
|
# note that the vpc_id does not need to be created in order to create
|
|
|
|
# a security group within the vpc when using moto
|
|
|
|
group_vpc = conn.create_security_group(name=group_name,
|
|
|
|
description=group_description,
|
|
|
|
vpc_id=vpc_id)
|
2014-08-11 18:52:30 +00:00
|
|
|
retrieved_group_id = boto_secgroup.get_group_id(group_name, group_vpc,
|
2014-08-04 00:04:20 +00:00
|
|
|
**conn_parameters)
|
2014-08-11 18:52:30 +00:00
|
|
|
self.assertEqual(group_vpc.id, retrieved_group_id)
|
2014-08-04 00:04:20 +00:00
|
|
|
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test_get_config_single_rule_group_name(self):
|
|
|
|
'''
|
|
|
|
tests return of 'config' when given group name. get_config returns an OrderedDict.
|
|
|
|
'''
|
|
|
|
group_name = _random_group_name()
|
2016-05-02 16:46:19 +00:00
|
|
|
ip_protocol = u'tcp'
|
2014-08-05 03:45:00 +00:00
|
|
|
from_port = 22
|
|
|
|
to_port = 22
|
2016-05-02 16:46:19 +00:00
|
|
|
cidr_ip = u'0.0.0.0/0'
|
|
|
|
rules_egress = [{'to_port': -1, 'from_port': -1, 'ip_protocol': u'-1', 'cidr_ip': u'0.0.0.0/0'}]
|
|
|
|
|
2014-08-15 01:12:43 +00:00
|
|
|
conn = boto.ec2.connect_to_region(region, **boto_conn_parameters)
|
2014-08-05 03:45:00 +00:00
|
|
|
group = conn.create_security_group(name=group_name, description=group_name)
|
|
|
|
group.authorize(ip_protocol=ip_protocol, from_port=from_port, to_port=to_port, cidr_ip=cidr_ip)
|
|
|
|
# setup the expected get_config result
|
|
|
|
expected_get_config_result = OrderedDict([('name', group.name), ('group_id', group.id), ('owner_id', u'111122223333'),
|
|
|
|
('description', group.description),
|
|
|
|
('rules', [{'to_port': to_port, 'from_port': from_port,
|
2015-05-04 02:13:05 +00:00
|
|
|
'ip_protocol': ip_protocol, 'cidr_ip': cidr_ip}]),
|
2016-05-02 16:46:19 +00:00
|
|
|
('rules_egress', rules_egress)])
|
2014-08-05 03:45:00 +00:00
|
|
|
secgroup_get_config_result = boto_secgroup.get_config(group_id=group.id, **conn_parameters)
|
|
|
|
self.assertEqual(expected_get_config_result, secgroup_get_config_result)
|
|
|
|
|
2014-08-15 01:12:43 +00:00
|
|
|
@skipIf(True, 'test skipped due to error in moto return - fixed in '
|
|
|
|
'https://github.com/spulec/moto/commit/cc0166964371f7b5247a49d45637a8f936ccbe6f')
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test_exists_true_name_classic(self):
|
|
|
|
'''
|
|
|
|
tests 'true' existence of a group in EC2-Classic when given name
|
|
|
|
'''
|
|
|
|
group_name = _random_group_name()
|
|
|
|
group_description = 'test_exists_true_ec2_classic'
|
2014-08-15 01:12:43 +00:00
|
|
|
conn = boto.ec2.connect_to_region(region, **boto_conn_parameters)
|
2014-08-05 03:45:00 +00:00
|
|
|
group_classic = conn.create_security_group(group_name, group_description)
|
|
|
|
group_vpc = conn.create_security_group(group_name, group_description, vpc_id=vpc_id)
|
|
|
|
salt_exists_result = boto_secgroup.exists(name=group_name, **conn_parameters)
|
|
|
|
self.assertTrue(salt_exists_result)
|
|
|
|
|
|
|
|
@skipIf(True, 'test skipped because moto does not yet support group'
|
|
|
|
' filters https://github.com/spulec/moto/issues/154')
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test_exists_false_name_classic(self):
|
|
|
|
pass
|
|
|
|
|
2014-08-15 01:12:43 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test_exists_true_name_vpc(self):
|
|
|
|
'''
|
|
|
|
tests 'true' existence of a group in EC2-VPC when given name and vpc_id
|
|
|
|
'''
|
|
|
|
group_name = _random_group_name()
|
|
|
|
group_description = 'test_exists_true_ec2_vpc'
|
2014-08-15 01:12:43 +00:00
|
|
|
conn = boto.ec2.connect_to_region(region, **boto_conn_parameters)
|
2014-08-05 03:45:00 +00:00
|
|
|
conn.create_security_group(group_name, group_description, vpc_id=vpc_id)
|
|
|
|
salt_exists_result = boto_secgroup.exists(name=group_name, vpc_id=vpc_id, **conn_parameters)
|
|
|
|
self.assertTrue(salt_exists_result)
|
|
|
|
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test_exists_false_name_vpc(self):
|
|
|
|
'''
|
|
|
|
tests 'false' existence of a group in vpc when given name and vpc_id
|
|
|
|
'''
|
|
|
|
group_name = _random_group_name()
|
|
|
|
salt_exists_result = boto_secgroup.exists(group_name, vpc_id=vpc_id, **conn_parameters)
|
|
|
|
self.assertFalse(salt_exists_result)
|
|
|
|
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test_exists_true_group_id(self):
|
|
|
|
'''
|
|
|
|
tests 'true' existence of a group when given group_id
|
|
|
|
'''
|
|
|
|
group_name = _random_group_name()
|
|
|
|
group_description = 'test_exists_true_group_id'
|
2014-08-15 01:12:43 +00:00
|
|
|
conn = boto.ec2.connect_to_region(region, **boto_conn_parameters)
|
2014-08-05 03:45:00 +00:00
|
|
|
group = conn.create_security_group(group_name, group_description)
|
|
|
|
salt_exists_result = boto_secgroup.exists(group_id=group.id, **conn_parameters)
|
|
|
|
self.assertTrue(salt_exists_result)
|
|
|
|
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test_exists_false_group_id(self):
|
|
|
|
'''
|
|
|
|
tests 'false' existence of a group when given group_id
|
|
|
|
'''
|
|
|
|
group_id = _random_group_id()
|
|
|
|
salt_exists_result = boto_secgroup.exists(group_id=group_id, **conn_parameters)
|
|
|
|
self.assertFalse(salt_exists_result)
|
|
|
|
|
|
|
|
@skipIf(True, 'test skipped due to error in moto return - fixed in'
|
|
|
|
' https://github.com/spulec/moto/commit/cc0166964371f7b5247a49d45637a8f936ccbe6f')
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test_delete_group_ec2_classic(self):
|
|
|
|
'''
|
|
|
|
test deletion of a group in EC2-Classic. Test does the following:
|
|
|
|
1. creates two groups, in EC2-Classic and one in EC2-VPC
|
|
|
|
2. saves the group_ids to group_ids_pre_delete
|
|
|
|
3. removes the group in EC2-VPC
|
|
|
|
4. saves the group ids of groups to group_ids_post_delete
|
|
|
|
5. compares the group_ids_pre_delete and group_ids_post_delete lists
|
|
|
|
to ensure that the correct group was deleted
|
|
|
|
'''
|
|
|
|
group_name = _random_group_name()
|
|
|
|
group_description = 'test_delete_group_ec2_classic'
|
|
|
|
# create two groups using boto, one in EC2-Classic and one in EC2-VPC
|
2014-08-15 01:12:43 +00:00
|
|
|
conn = boto.ec2.connect_to_region(region, **boto_conn_parameters)
|
2014-08-05 03:45:00 +00:00
|
|
|
group_classic = conn.create_security_group(name=group_name, description=group_description)
|
|
|
|
group_vpc = conn.create_security_group(name=group_name, description=group_description, vpc_id=vpc_id)
|
|
|
|
# creates a list of all the existing all_group_ids in an AWS account
|
|
|
|
all_groups = [group.id for group in conn.get_all_security_groups()]
|
|
|
|
# removes the EC2-Classic Security Group
|
|
|
|
deleted = boto_secgroup.delete(name=group_name, **conn_parameters)
|
|
|
|
expected_groups = deepcopy(all_groups)
|
|
|
|
expected_groups.remove(group_classic.id)
|
|
|
|
actual_groups = [group.id for group in conn.get_all_security_groups()]
|
|
|
|
self.assertEqual(expected_groups, actual_groups)
|
|
|
|
|
|
|
|
@skipIf(True, 'test skipped because moto does not yet support group'
|
|
|
|
' filters https://github.com/spulec/moto/issues/154')
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test_delete_group_name_ec2_vpc(self):
|
|
|
|
pass
|
|
|
|
|
2014-08-12 15:20:17 +00:00
|
|
|
@mock_ec2
|
2014-08-05 03:45:00 +00:00
|
|
|
def test__get_conn_true(self):
|
|
|
|
'''
|
|
|
|
tests ensures that _get_conn returns an boto.ec2.connection.EC2Connection object.
|
|
|
|
'''
|
2014-08-15 01:12:43 +00:00
|
|
|
conn = boto.ec2.connect_to_region(region, **boto_conn_parameters)
|
2014-08-05 03:45:00 +00:00
|
|
|
salt_conn = boto_secgroup._get_conn(**conn_parameters)
|
|
|
|
self.assertEqual(conn.__class__, salt_conn.__class__)
|
|
|
|
|
2014-07-23 17:43:28 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2015-02-23 19:24:53 +00:00
|
|
|
from integration import run_tests # pylint: disable=import-error
|
2014-08-12 22:57:34 +00:00
|
|
|
run_tests(BotoSecgroupTestCase, needs_daemon=False)
|