Issue: LIBCLOUD-466 Add ingress/egress VPC support to security group rules.

Signed-off-by: Tomaz Muraus <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/57393395
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/57393395
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/57393395

Branch: refs/heads/trunk
Commit: 573933951172b0b23673dcb2689d1adc089dd144
Parents: 5e4233c
Author: Chris DeRamus <[email protected]>
Authored: Fri Dec 20 11:26:23 2013 -0500
Committer: Tomaz Muraus <[email protected]>
Committed: Sat Dec 21 15:02:56 2013 +0100

----------------------------------------------------------------------
 libcloud/compute/drivers/ec2.py                 | 256 +++++++++++++++++++
 .../ec2/authorize_security_group_egress.xml     |   4 +
 .../ec2/revoke_security_group_egress.xml        |   4 +
 .../ec2/revoke_security_group_ingress.xml       |   4 +
 libcloud/test/compute/test_ec2.py               |  32 +++
 5 files changed, 300 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/57393395/libcloud/compute/drivers/ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py
index 2f8dcfe..805f025 100644
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@ -776,6 +776,42 @@ class BaseEC2NodeDriver(NodeDriver):
                                      'description': description,
                                      'state': state})
 
+    def _get_common_security_group_params(self, group_id, protocol,
+                                          from_port, to_port, cidr_ips,
+                                          group_pairs):
+
+        params = {'GroupId': id,
+                  'IpPermissions.1.IpProtocol': protocol,
+                  'IpPermissions.1.FromPort': from_port,
+                  'IpPermissions.1.ToPort': to_port}
+
+        if cidr_ips is not None:
+            ip_ranges = {}
+            for index, cidr_ip in enumerate(cidr_ips, 1):
+                ip_ranges['IpPermissions.1.IpRanges.%s.CidrIp'
+                          % (index)] = cidr_ip
+
+            params.update(ip_ranges)
+
+        if group_pairs is not None:
+            user_groups = {}
+            for index, group_pair in enumerate(group_pairs, 1):
+                if 'group_id' in group_pair.keys():
+                    user_groups['IpPermissions.1.Groups.%s.GroupId'
+                                % (index)] = group_pair['group_id']
+
+                if 'group_name' in group_pair.keys():
+                    user_groups['IpPermissions.1.Groups.%s.GroupName'
+                                % (index)] = group_pair['group_name']
+
+                if 'user_id' in group_pair.keys():
+                    user_groups['IpPermissions.1.Groups.%s.UserId'
+                                % (index)] = group_pair['user_id']
+
+            params.update(user_groups)
+
+        return params
+
     def list_nodes(self, ex_node_ids=None):
         """
         List all nodes
@@ -1384,6 +1420,226 @@ class BaseEC2NodeDriver(NodeDriver):
             if e.args[0].find('InvalidPermission.Duplicate') == -1:
                 raise e
 
+    def ex_authorize_security_group_ingress(self, id, from_port, to_port,
+                                            cidr_ips=None, group_pairs=None,
+                                            protocol='tcp'):
+        """
+        Edit a Security Group to allow specific ingress traffic using
+        CIDR blocks or either a group ID, group name or user ID (account).
+
+        :param      id: The id of the security group to edit
+        :type       id: ``str``
+
+        :param      from_port: The beginning of the port range to open
+        :type       from_port: ``int``
+
+        :param      to_port: The end of the port range to open
+        :type       to_port: ``int``
+
+        :param      cidr_ips: The list of ip ranges to allow traffic for.
+        :type       cidr_ips: ``list``
+
+        :param      group_pairs: Source user/group pairs to allow traffic for.
+                    More info can be found at http://goo.gl/stBHJF
+
+                    EC2 Classic Example: To allow access from any system
+                    associated with the default group on account 1234567890
+
+                    [{'group_name': 'default', 'user_id': '1234567890'}]
+
+                    VPC Example: Allow access from any system associated with
+                    security group sg-47ad482e on your own account
+
+                    [{'group_id': ' sg-47ad482e'}]
+        :type       group_pairs: ``list`` of ``dict``
+
+        :param      protocol: tcp/udp/icmp
+        :type       protocol: ``str``
+
+        :rtype: ``bool``
+        """
+
+        params = self._get_common_security_group_params(id,
+                                                        protocol,
+                                                        from_port,
+                                                        to_port,
+                                                        cidr_ips,
+                                                        group_pairs)
+
+        params["Action"] = 'AuthorizeSecurityGroupIngress'
+
+        result = self.connection.request(self.path, params=params).object
+        element = findtext(element=result, xpath='return',
+                           namespace=NAMESPACE)
+
+        return element == 'true'
+
+    def ex_authorize_security_group_egress(self, id, from_port, to_port,
+                                           cidr_ips=None, group_pairs=None,
+                                           protocol='tcp'):
+        """
+        Edit a Security Group to allow specific egress traffic using
+        CIDR blocks or either a group ID, group name or user ID (account).
+        This call is not supported for EC2 classic and only works for VPC
+        groups.
+
+        :param      id: The id of the security group to edit
+        :type       id: ``str``
+
+        :param      from_port: The beginning of the port range to open
+        :type       from_port: ``int``
+
+        :param      to_port: The end of the port range to open
+        :type       to_port: ``int``
+
+        :param      cidr_ips: The list of ip ranges to allow traffic for.
+        :type       cidr_ips: ``list``
+
+        :param      group_pairs: Source user/group pairs to allow traffic for.
+                    More info can be found at http://goo.gl/stBHJF
+
+                    EC2 Classic Example: To allow access from any system
+                    associated with the default group on account 1234567890
+
+                    [{'group_name': 'default', 'user_id': '1234567890'}]
+
+                    VPC Example: Allow access from any system associated with
+                    security group sg-47ad482e on your own account
+
+                    [{'group_id': ' sg-47ad482e'}]
+        :type       group_pairs: ``list`` of ``dict``
+
+        :param      protocol: tcp/udp/icmp
+        :type       protocol: ``str``
+
+        :rtype: ``bool``
+        """
+
+        params = self._get_common_security_group_params(id,
+                                                        protocol,
+                                                        from_port,
+                                                        to_port,
+                                                        cidr_ips,
+                                                        group_pairs)
+
+        params["Action"] = 'AuthorizeSecurityGroupEgress'
+
+        result = self.connection.request(self.path, params=params).object
+        element = findtext(element=result, xpath='return',
+                           namespace=NAMESPACE)
+
+        return element == 'true'
+
+    def ex_revoke_security_group_ingress(self, id, from_port, to_port,
+                                         cidr_ips=None, group_pairs=None,
+                                         protocol='tcp'):
+        """
+        Edit a Security Group to revoke specific ingress traffic using
+        CIDR blocks or either a group ID, group name or user ID (account).
+
+        :param      id: The id of the security group to edit
+        :type       id: ``str``
+
+        :param      from_port: The beginning of the port range to open
+        :type       from_port: ``int``
+
+        :param      to_port: The end of the port range to open
+        :type       to_port: ``int``
+
+        :param      cidr_ips: The list of ip ranges to allow traffic for.
+        :type       cidr_ips: ``list``
+
+        :param      group_pairs: Source user/group pairs to allow traffic for.
+                    More info can be found at http://goo.gl/stBHJF
+
+                    EC2 Classic Example: To allow access from any system
+                    associated with the default group on account 1234567890
+
+                    [{'group_name': 'default', 'user_id': '1234567890'}]
+
+                    VPC Example: Allow access from any system associated with
+                    security group sg-47ad482e on your own account
+
+                    [{'group_id': ' sg-47ad482e'}]
+        :type       group_pairs: ``list`` of ``dict``
+
+        :param      protocol: tcp/udp/icmp
+        :type       protocol: ``str``
+
+        :rtype: ``bool``
+        """
+
+        params = self._get_common_security_group_params(id,
+                                                        protocol,
+                                                        from_port,
+                                                        to_port,
+                                                        cidr_ips,
+                                                        group_pairs)
+
+        params["Action"] = 'RevokeSecurityGroupIngress'
+
+        result = self.connection.request(self.path, params=params).object
+        element = findtext(element=result, xpath='return',
+                           namespace=NAMESPACE)
+
+        return element == 'true'
+
+    def ex_revoke_security_group_egress(self, id, from_port, to_port,
+                                        cidr_ips=None, group_pairs=None,
+                                        protocol='tcp'):
+        """
+        Edit a Security Group to revoke specific egress traffic using
+        CIDR blocks or either a group ID, group name or user ID (account).
+        This call is not supported for EC2 classic and only works for
+        VPC groups.
+
+        :param      id: The id of the security group to edit
+        :type       id: ``str``
+
+        :param      from_port: The beginning of the port range to open
+        :type       from_port: ``int``
+
+        :param      to_port: The end of the port range to open
+        :type       to_port: ``int``
+
+        :param      cidr_ips: The list of ip ranges to allow traffic for.
+        :type       cidr_ips: ``list``
+
+        :param      group_pairs: Source user/group pairs to allow traffic for.
+                    More info can be found at http://goo.gl/stBHJF
+
+                    EC2 Classic Example: To allow access from any system
+                    associated with the default group on account 1234567890
+
+                    [{'group_name': 'default', 'user_id': '1234567890'}]
+
+                    VPC Example: Allow access from any system associated with
+                    security group sg-47ad482e on your own account
+
+                    [{'group_id': ' sg-47ad482e'}]
+        :type       group_pairs: ``list`` of ``dict``
+
+        :param      protocol: tcp/udp/icmp
+        :type       protocol: ``str``
+
+        :rtype: ``bool``
+        """
+
+        params = self._get_common_security_group_params(id,
+                                                        protocol,
+                                                        from_port,
+                                                        to_port,
+                                                        cidr_ips,
+                                                        group_pairs)
+
+        params['Action'] = 'RevokeSecurityGroupEgress'
+
+        result = self.connection.request(self.path, params=params).object
+        element = findtext(element=result, xpath='return',
+                           namespace=NAMESPACE)
+
+        return element == 'true'
+
     def ex_authorize_security_group_permissive(self, name):
         """
         Edit a Security Group to allow all traffic.

http://git-wip-us.apache.org/repos/asf/libcloud/blob/57393395/libcloud/test/compute/fixtures/ec2/authorize_security_group_egress.xml
----------------------------------------------------------------------
diff --git 
a/libcloud/test/compute/fixtures/ec2/authorize_security_group_egress.xml 
b/libcloud/test/compute/fixtures/ec2/authorize_security_group_egress.xml
new file mode 100644
index 0000000..41e7e46
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/authorize_security_group_egress.xml
@@ -0,0 +1,4 @@
+<AuthorizeSecurityGroupEgressResponse 
xmlns="http://ec2.amazonaws.com/doc/2013-10-15/";>
+  <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
+  <return>true</return>
+</AuthorizeSecurityGroupEgressResponse>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/57393395/libcloud/test/compute/fixtures/ec2/revoke_security_group_egress.xml
----------------------------------------------------------------------
diff --git 
a/libcloud/test/compute/fixtures/ec2/revoke_security_group_egress.xml 
b/libcloud/test/compute/fixtures/ec2/revoke_security_group_egress.xml
new file mode 100644
index 0000000..248fbb7
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/revoke_security_group_egress.xml
@@ -0,0 +1,4 @@
+<RevokeSecurityGroupEgressResponse 
xmlns="http://ec2.amazonaws.com/doc/2013-10-15/";>
+  <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
+  <return>true</return>
+</RevokeSecurityGroupEgressResponse>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/57393395/libcloud/test/compute/fixtures/ec2/revoke_security_group_ingress.xml
----------------------------------------------------------------------
diff --git 
a/libcloud/test/compute/fixtures/ec2/revoke_security_group_ingress.xml 
b/libcloud/test/compute/fixtures/ec2/revoke_security_group_ingress.xml
new file mode 100644
index 0000000..26708da
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/revoke_security_group_ingress.xml
@@ -0,0 +1,4 @@
+<RevokeSecurityGroupIngressResponse 
xmlns="http://ec2.amazonaws.com/doc/2013-10-15/";>
+  <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
+  <return>true</return>
+</RevokeSecurityGroupIngressResponse>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/57393395/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ec2.py 
b/libcloud/test/compute/test_ec2.py
index 4364d69..1a843fd 100644
--- a/libcloud/test/compute/test_ec2.py
+++ b/libcloud/test/compute/test_ec2.py
@@ -220,6 +220,38 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
                                                        '0.0.0.0/0')
         self.assertTrue(resp)
 
+    def test_authorize_security_group_ingress(self):
+        ranges = ['1.1.1.1/32', '2.2.2.2/32']
+        resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 
22, 22, cidr_ips=ranges)
+        self.assertTrue(resp)
+        groups = [{'group_id': 'sg-949265ff'}]
+        resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 
22, 23, group_pairs=groups)
+        self.assertTrue(resp)
+
+    def test_authorize_security_group_egress(self):
+        ranges = ['1.1.1.1/32', '2.2.2.2/32']
+        resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 
22, 22, cidr_ips=ranges)
+        self.assertTrue(resp)
+        groups = [{'group_id': 'sg-949265ff'}]
+        resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 
22, 22, group_pairs=groups)
+        self.assertTrue(resp)
+
+    def test_revoke_security_group_ingress(self):
+        ranges = ['1.1.1.1/32', '2.2.2.2/32']
+        resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 
22, 22, cidr_ips=ranges)
+        self.assertTrue(resp)
+        groups = [{'group_id': 'sg-949265ff'}]
+        resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 
22, 22, group_pairs=groups)
+        self.assertTrue(resp)
+
+    def test_revoke_security_group_egress(self):
+        ranges = ['1.1.1.1/32', '2.2.2.2/32']
+        resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 
22, 22, cidr_ips=ranges)
+        self.assertTrue(resp)
+        groups = [{'group_id': 'sg-949265ff'}]
+        resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 
22, 22, group_pairs=groups)
+        self.assertTrue(resp)
+
     def test_reboot_node(self):
         node = Node('i-4382922a', None, None, None, None, self.driver)
         ret = self.driver.reboot_node(node)

Reply via email to