diff --git a/moto/ec2/models.py b/moto/ec2/models.py index 779322df1..f86b1852c 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -1323,6 +1323,53 @@ class SecurityGroupBackend(object): raise InvalidPermissionNotFoundError() + def authorize_security_group_egress(self, + group_name_or_id, + ip_protocol, + from_port, + to_port, + ip_ranges, + src_group_id=None, + cidr_ip=None, + vpc_id=None): + + group = self.get_security_group_by_name_or_id(group_name_or_id, vpc_id) + + if ip_ranges and not isinstance(ip_ranges, list): + ip_ranges = [ip_ranges] + + # for VPCs + source_groups = [] + source_group = self.get_security_group_from_id(src_group_id) + if source_group: + source_groups.append(source_group) + security_rule = SecurityRule(ip_protocol, from_port, to_port, ip_ranges, source_groups) + group.egress_rules.append(security_rule) + + def revoke_security_group_egress(self, + group_name_or_id, + ip_protocol, + from_port, + to_port, + ip_ranges, + source_group_names=None, + source_group_ids=None, + vpc_id=None): + + group = self.get_security_group_by_name_or_id(group_name_or_id, vpc_id) + + source_groups = [] + for source_group_name in source_group_names: + source_group = self.get_security_group_from_name(source_group_name, vpc_id) + if source_group: + source_groups.append(source_group) + + security_rule = SecurityRule(ip_protocol, from_port, to_port, ip_ranges, source_groups) + if security_rule in group.egress_rules: + group.egress_rules.remove(security_rule) + return security_rule + raise InvalidPermissionNotFoundError() + class SecurityGroupIngress(object): diff --git a/moto/ec2/responses/security_groups.py b/moto/ec2/responses/security_groups.py index 9a9aaafd9..55c996fff 100644 --- a/moto/ec2/responses/security_groups.py +++ b/moto/ec2/responses/security_groups.py @@ -31,7 +31,8 @@ def process_rules_from_querystring(querystring): class SecurityGroups(BaseResponse): def authorize_security_group_egress(self): - raise NotImplementedError('SecurityGroups.authorize_security_group_egress is not yet implemented') + self.ec2_backend.authorize_security_group_egress(*process_rules_from_querystring(self.querystring)) + return AUTHORIZE_SECURITY_GROUP_EGRESS_RESPONSE def authorize_security_group_ingress(self): self.ec2_backend.authorize_security_group_ingress(*process_rules_from_querystring(self.querystring)) @@ -73,7 +74,10 @@ class SecurityGroups(BaseResponse): return template.render(groups=groups) def revoke_security_group_egress(self): - raise NotImplementedError('SecurityGroups.revoke_security_group_egress is not yet implemented') + success = self.ec2_backend.revoke_security_group_egress(*process_rules_from_querystring(self.querystring)) + if not success: + return "Could not find a matching egress rule", dict(status=404) + return REVOKE_SECURITY_GROUP_EGRESS_RESPONSE def revoke_security_group_ingress(self): self.ec2_backend.revoke_security_group_ingress(*process_rules_from_querystring(self.querystring)) @@ -128,7 +132,31 @@ DESCRIBE_SECURITY_GROUPS_RESPONSE = """59dbff89-35bd-4eac-99ed-be587EXAMPLE true """ + +AUTHORIZE_SECURITY_GROUP_EGRESS_RESPONSE = """ + + 59dbff89-35bd-4eac-99ed-be587EXAMPLE + true +""" + +REVOKE_SECURITY_GROUP_EGRESS_RESPONSE = """ + 59dbff89-35bd-4eac-99ed-be587EXAMPLE + true +""" diff --git a/tests/test_ec2/test_security_groups.py b/tests/test_ec2/test_security_groups.py index b39ffac70..a36713d68 100644 --- a/tests/test_ec2/test_security_groups.py +++ b/tests/test_ec2/test_security_groups.py @@ -152,6 +152,23 @@ def test_authorize_ip_range_and_revoke(): security_group = conn.get_all_security_groups()[0] security_group.rules.should.have.length_of(0) + # Test for egress as well + egress_security_group = conn.create_security_group('testegress', 'testegress', vpc_id='vpc-3432589') + success = conn.authorize_security_group_egress(egress_security_group.id, "tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32") + assert success.should.be.true + egress_security_group = conn.get_all_security_groups(groupnames='testegress')[0] + int(egress_security_group.rules_egress[0].to_port).should.equal(2222) + egress_security_group.rules_egress[0].grants[0].cidr_ip.should.equal("123.123.123.123/32") + + # Wrong Cidr should throw error + egress_security_group.revoke.when.called_with(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.122/32").should.throw(EC2ResponseError) + + # Actually revoke + conn.revoke_security_group_egress(egress_security_group.id, "tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32") + + egress_security_group = conn.get_all_security_groups()[0] + egress_security_group.rules_egress.should.have.length_of(0) + @mock_ec2 def test_authorize_other_group_and_revoke():