Allow to configure CIDR exclusion blocks

This commit is contained in:
Ignasi Barrera 2014-10-10 00:47:53 +02:00
parent 2caf6ea86e
commit e5fb0b607d
11 changed files with 209 additions and 33 deletions

View File

@ -279,4 +279,9 @@ public class CloudStackSecurityGroupExtension implements SecurityGroupExtension
return false;
}
@Override
public boolean supportsExclusionCidrBlocks() {
return false;
}
}

View File

@ -333,6 +333,11 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
return false;
}
@Override
public boolean supportsExclusionCidrBlocks() {
return false;
}
protected Iterable<? extends org.jclouds.ec2.domain.SecurityGroup> pollSecurityGroups() {
Iterable<? extends Set<? extends org.jclouds.ec2.domain.SecurityGroup>> groups
= transform(regions.get(), allSecurityGroupsInRegion());

View File

@ -42,7 +42,7 @@ public class IpPermissions extends IpPermission {
protected IpPermissions(IpProtocol ipProtocol, int fromPort, int toPort,
Multimap<String, String> userIdGroupPairs, Iterable<String> groupIds, Iterable<String> ipRanges) {
super(ipProtocol, fromPort, toPort, userIdGroupPairs, groupIds, userIdGroupPairs.isEmpty() ? ipRanges
: ImmutableSet.<String> of());
: ImmutableSet.<String> of(), ImmutableSet.<String> of());
}
/**

View File

@ -46,10 +46,10 @@ public class DescribeSecurityGroupsResponseHandlerTest extends BaseEC2HandlerTes
Set<SecurityGroup> expected = ImmutableSet.of(
new SecurityGroup(defaultRegion, "sg-3c6ef654", "WebServers", "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", "Web Servers",
ImmutableSet.of(new IpPermission(IpProtocol.TCP, 80, 80, ImmutableMultimap.<String, String> of(),
ImmutableSet.<String> of(), ImmutableSet.of("0.0.0.0/0")))),
ImmutableSet.<String> of(), ImmutableSet.of("0.0.0.0/0"), ImmutableSet.<String> of()))),
new SecurityGroup(defaultRegion, "sg-867309ab", "RangedPortsBySource", "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", "Group A",
ImmutableSet.of(new IpPermission(IpProtocol.TCP, 6000, 7000, ImmutableMultimap
.<String, String> of(), ImmutableSet.<String> of(), ImmutableSet.<String> of()))));
.<String, String> of(), ImmutableSet.<String> of(), ImmutableSet.<String> of(), ImmutableSet.<String> of()))));
DescribeSecurityGroupsResponseHandler handler = injector.getInstance(DescribeSecurityGroupsResponseHandler.class);
addDefaultRegionToHandler(handler);
@ -70,9 +70,9 @@ public class DescribeSecurityGroupsResponseHandlerTest extends BaseEC2HandlerTes
new SecurityGroup(defaultRegion, "sg-3c6ef654", "jclouds#cluster#world", "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", "Cluster",
ImmutableSet.of(
new IpPermission(IpProtocol.TCP, 22, 22, ImmutableMultimap.<String, String> of(),
ImmutableSet.<String> of(), ImmutableSet.of("0.0.0.0/0")),
ImmutableSet.<String> of(), ImmutableSet.of("0.0.0.0/0"), ImmutableSet.<String> of()),
new IpPermission(IpProtocol.ALL, -1, -1, userIdGroupPairs,
ImmutableSet.<String> of(), ImmutableSet.<String> of()))));
ImmutableSet.<String> of(), ImmutableSet.<String> of(), ImmutableSet.<String> of()))));
DescribeSecurityGroupsResponseHandler handler = injector.getInstance(DescribeSecurityGroupsResponseHandler.class);
addDefaultRegionToHandler(handler);

View File

@ -330,6 +330,11 @@ public class NovaSecurityGroupExtension implements SecurityGroupExtension {
return false;
}
@Override
public boolean supportsExclusionCidrBlocks() {
return false;
}
protected Iterable<? extends SecurityGroupInRegion> pollSecurityGroups() {
Iterable<? extends Set<? extends SecurityGroupInRegion>> groups
= transform(regionIds.get(), allSecurityGroupsInRegion());
@ -368,4 +373,5 @@ public class NovaSecurityGroupExtension implements SecurityGroupExtension {
}
};
}
}

View File

@ -23,6 +23,7 @@ import org.jclouds.domain.Location;
import org.jclouds.net.domain.IpPermission;
import org.jclouds.net.domain.IpProtocol;
import com.google.common.annotations.Beta;
import com.google.common.collect.Multimap;
/**
@ -180,4 +181,10 @@ public interface SecurityGroupExtension {
*/
boolean supportsPortRangesForGroups();
/**
* Returns true if this SecurityGroupExtension supports exclusion CIDR groups.
*/
@Beta
boolean supportsExclusionCidrBlocks();
}

View File

@ -245,4 +245,9 @@ public class StubSecurityGroupExtension implements SecurityGroupExtension {
public boolean supportsPortRangesForGroups() {
return true;
}
@Override
public boolean supportsExclusionCidrBlocks() {
return true;
}
}

View File

@ -56,6 +56,7 @@ public class IpPermission implements Comparable<IpPermission> {
private Multimap<String, String> tenantIdGroupNamePairs = LinkedHashMultimap.create();
private Set<String> groupIds = Sets.newLinkedHashSet();
private Set<String> cidrBlocks = Sets.newLinkedHashSet();
private Set<String> exclusionCidrBlocks = Sets.newLinkedHashSet();
/**
*
@ -113,13 +114,36 @@ public class IpPermission implements Comparable<IpPermission> {
* @see IpPermission#getCidrBlocks()
*/
public Builder cidrBlocks(Iterable<String> cidrBlocks) {
Iterables.addAll(this.cidrBlocks, transform(cidrBlocks,
new Function<String, String>() {
Iterables.addAll(this.cidrBlocks, transform(cidrBlocks, new Function<String, String>() {
@Override
public String apply(String input) {
checkArgument(isCidrFormat(input),
"input %s is not a valid CIDR",
input);
checkArgument(isCidrFormat(input), "input %s is not a valid CIDR", input);
return input;
}
}));
return this;
}
/**
* @see IpPermission#getExclusionCidrBlocks()
*/
@Beta
public Builder exclusionCidrBlock(String exclusionCidrBlock) {
checkArgument(isCidrFormat(exclusionCidrBlock), "exclusionCidrBlock %s is not a valid CIDR",
exclusionCidrBlock);
this.exclusionCidrBlocks.add(exclusionCidrBlock);
return this;
}
/**
* @see IpPermission#getExclusionCidrBlocks()
*/
@Beta
public Builder exclusionCidrBlocks(Iterable<String> exclusionCidrBlocks) {
Iterables.addAll(this.exclusionCidrBlocks, transform(exclusionCidrBlocks, new Function<String, String>() {
@Override
public String apply(String input) {
checkArgument(isCidrFormat(input), "input %s is not a valid CIDR", input);
return input;
}
}));
@ -143,7 +167,8 @@ public class IpPermission implements Comparable<IpPermission> {
}
public IpPermission build() {
return new IpPermission(ipProtocol, fromPort, toPort, tenantIdGroupNamePairs, groupIds, cidrBlocks);
return new IpPermission(ipProtocol, fromPort, toPort, tenantIdGroupNamePairs, groupIds, cidrBlocks,
exclusionCidrBlocks);
}
}
@ -153,9 +178,11 @@ public class IpPermission implements Comparable<IpPermission> {
private final Set<String> groupIds;
private final IpProtocol ipProtocol;
private final Set<String> cidrBlocks;
private final Set<String> exclusionCidrBlocks;
public IpPermission(IpProtocol ipProtocol, int fromPort, int toPort,
Multimap<String, String> tenantIdGroupNamePairs, Iterable<String> groupIds, Iterable<String> cidrBlocks) {
Multimap<String, String> tenantIdGroupNamePairs, Iterable<String> groupIds, Iterable<String> cidrBlocks,
Iterable<String> exclusionCidrBlocks) {
this.fromPort = fromPort;
this.toPort = toPort;
this.tenantIdGroupNamePairs = ImmutableMultimap.copyOf(checkNotNull(tenantIdGroupNamePairs,
@ -163,6 +190,7 @@ public class IpPermission implements Comparable<IpPermission> {
this.ipProtocol = checkNotNull(ipProtocol, "ipProtocol");
this.groupIds = ImmutableSet.copyOf(checkNotNull(groupIds, "groupIds"));
this.cidrBlocks = ImmutableSet.copyOf(checkNotNull(cidrBlocks, "cidrBlocks"));
this.exclusionCidrBlocks = ImmutableSet.copyOf(checkNotNull(exclusionCidrBlocks, "exclusionCidrBlocks"));
}
/**
@ -217,6 +245,14 @@ public class IpPermission implements Comparable<IpPermission> {
return cidrBlocks;
}
/**
* source of traffic is a all but this exclusionCidrBlocks
*/
@Beta
public Set<String> getExclusionCidrBlocks() {
return exclusionCidrBlocks;
}
@Override
public boolean equals(Object o) {
if (this == o)
@ -227,12 +263,14 @@ public class IpPermission implements Comparable<IpPermission> {
IpPermission that = IpPermission.class.cast(o);
return equal(this.ipProtocol, that.ipProtocol) && equal(this.fromPort, that.fromPort)
&& equal(this.toPort, that.toPort) && equal(this.tenantIdGroupNamePairs, that.tenantIdGroupNamePairs)
&& equal(this.groupIds, that.groupIds) && equal(this.cidrBlocks, that.cidrBlocks);
&& equal(this.groupIds, that.groupIds) && equal(this.cidrBlocks, that.cidrBlocks)
&& equal(this.exclusionCidrBlocks, that.exclusionCidrBlocks);
}
@Override
public int hashCode() {
return Objects.hashCode(ipProtocol, fromPort, toPort, tenantIdGroupNamePairs, groupIds, cidrBlocks);
return Objects.hashCode(ipProtocol, fromPort, toPort, tenantIdGroupNamePairs, groupIds, cidrBlocks,
exclusionCidrBlocks);
}
@Override
@ -241,9 +279,9 @@ public class IpPermission implements Comparable<IpPermission> {
}
protected ToStringHelper string() {
return MoreObjects.toStringHelper("").add("ipProtocol", ipProtocol).add("fromPort", fromPort).add("toPort", toPort)
.add("tenantIdGroupNamePairs", tenantIdGroupNamePairs).add("groupIds", groupIds).add("cidrBlocks",
cidrBlocks);
return MoreObjects.toStringHelper("").add("ipProtocol", ipProtocol).add("fromPort", fromPort)
.add("toPort", toPort).add("tenantIdGroupNamePairs", tenantIdGroupNamePairs).add("groupIds", groupIds)
.add("cidrBlocks", cidrBlocks).add("exclusionCidrBlocks", exclusionCidrBlocks);
}
}

View File

@ -32,9 +32,11 @@ import com.google.common.collect.Multimap;
public class IpPermissions extends IpPermission {
protected IpPermissions(IpProtocol ipProtocol, int fromPort, int toPort,
Multimap<String, String> tenantIdGroupPairs, Iterable<String> groupIds, Iterable<String> cidrBlocks) {
Multimap<String, String> tenantIdGroupPairs, Iterable<String> groupIds, Iterable<String> cidrBlocks,
Iterable<String> exclusionCidrBlocks) {
super(ipProtocol, fromPort, toPort, tenantIdGroupPairs, groupIds, tenantIdGroupPairs.size() == 0 ? cidrBlocks
: ImmutableSet.<String> of());
: ImmutableSet.<String> of(), tenantIdGroupPairs.size() == 0 ? exclusionCidrBlocks : ImmutableSet
.<String> of());
}
public static ICMPTypeSelection permitICMP() {
@ -105,7 +107,7 @@ public class IpPermissions extends IpPermission {
protected ToGroupSourceSelection(IpProtocol ipProtocol, int fromPort, int toPort) {
super(ipProtocol, fromPort, toPort, ImmutableMultimap.<String, String> of(), ImmutableSet.<String> of(),
ImmutableSet.of("0.0.0.0/0"));
ImmutableSet.of("0.0.0.0/0"), ImmutableSet.<String> of());
}
public IpPermissions originatingFromSecurityGroupId(String groupId) {
@ -114,7 +116,7 @@ public class IpPermissions extends IpPermission {
public IpPermissions originatingFromSecurityGroupIds(Iterable<String> groupIds) {
return new IpPermissions(getIpProtocol(), getFromPort(), getToPort(), getTenantIdGroupNamePairs(), groupIds,
ImmutableSet.<String> of());
ImmutableSet.<String> of(), ImmutableSet.<String> of());
}
}
@ -128,8 +130,17 @@ public class IpPermissions extends IpPermission {
}
public IpPermissions originatingFromCidrBlocks(Iterable<String> cidrIps) {
return new IpPermissions(getIpProtocol(), getFromPort(), getToPort(),
ImmutableMultimap.<String, String> of(), ImmutableSet.<String> of(), cidrIps);
return new IpPermissions(getIpProtocol(), getFromPort(), getToPort(), ImmutableMultimap.<String, String> of(),
ImmutableSet.<String> of(), cidrIps, ImmutableSet.<String> of());
}
public IpPermissions exceptOriginatingFromCidrBlock(String excludedCidrIp) {
return exceptOriginatingFromCidrBlocks(ImmutableSet.of(checkNotNull(excludedCidrIp, "excludedCidrIp")));
}
public IpPermissions exceptOriginatingFromCidrBlocks(Iterable<String> excludedCidrIps) {
return new IpPermissions(getIpProtocol(), getFromPort(), getToPort(), ImmutableMultimap.<String, String> of(),
ImmutableSet.<String> of(), ImmutableSet.<String> of(), excludedCidrIps);
}
public IpPermissions originatingFromTenantAndSecurityGroup(String tenantId, String groupName) {
@ -139,7 +150,7 @@ public class IpPermissions extends IpPermission {
public IpPermissions toTenantsGroupsNamed(Multimap<String, String> tenantIdGroupNamePairs) {
return new IpPermissions(getIpProtocol(), getFromPort(), getToPort(), tenantIdGroupNamePairs, getGroupIds(),
ImmutableSet.<String> of());
ImmutableSet.<String> of(), ImmutableSet.<String> of());
}
}
}

View File

@ -17,6 +17,7 @@
package org.jclouds.compute.extensions.internal;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.util.Set;
@ -311,9 +312,57 @@ public abstract class BaseSecurityGroupExtensionLiveTest extends BaseComputeServ
}
*/
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testAddIpPermissionsFromSpec")
public void testAddIpPermissionWithCidrExclusionGroup() {
skipIfSecurityGroupsNotSupported();
ComputeService computeService = view.getComputeService();
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
if (!securityGroupExtension.get().supportsExclusionCidrBlocks()) {
throw new SkipException("Test cannot run without CIDR exclusion groups available.");
}
Optional<SecurityGroup> optGroup = getGroup(securityGroupExtension.get());
assertTrue(optGroup.isPresent());
SecurityGroup group = optGroup.get();
IpPermission cidrExclusionPermission = createCidrExclusionPermission();
Set<IpPermission> expectedPermissions = ImmutableSet.of(cidrExclusionPermission);
SecurityGroup securityGriupWithExclusion = securityGroupExtension.get().addIpPermission(cidrExclusionPermission, group);
assertTrue(securityGriupWithExclusion.getIpPermissions().containsAll(expectedPermissions));
}
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testAddIpPermissionWithCidrExclusionGroup")
public void testRemoveIpPermissionWithCidrExclusionGroup() {
skipIfSecurityGroupsNotSupported();
ComputeService computeService = view.getComputeService();
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
if (!securityGroupExtension.get().supportsExclusionCidrBlocks()) {
throw new SkipException("Test cannot run without CIDR exclusion groups available.");
}
Optional<SecurityGroup> optGroup = getGroup(securityGroupExtension.get());
assertTrue(optGroup.isPresent());
SecurityGroup group = optGroup.get();
IpPermission cidrExclusionPermission = createCidrExclusionPermission();
SecurityGroup emptyGroup = securityGroupExtension.get().removeIpPermission(cidrExclusionPermission, group);
assertFalse(emptyGroup.getIpPermissions().contains(cidrExclusionPermission));
}
// testDeleteSecurityGroup currently disabled until I can find a way to get it to delete the security group while a terminated
// instance is still floating around in EC2. - abayer, 6/14/13
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testAddIpPermissionsFromSpec")
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testRemoveIpPermissionWithCidrExclusionGroup", alwaysRun = true)
public void testDeleteSecurityGroup() {
skipIfSecurityGroupsNotSupported();
@ -358,6 +407,17 @@ public abstract class BaseSecurityGroupExtensionLiveTest extends BaseComputeServ
return builder.build();
}
private IpPermission createCidrExclusionPermission() {
IpPermission.Builder builder = IpPermission.builder();
builder.ipProtocol(IpProtocol.TCP);
builder.fromPort(10);
builder.toPort(20);
builder.exclusionCidrBlock("10.0.0.0/8");
return builder.build();
}
private IpPermission createSinglePortPermission() {
IpPermission.Builder builder = IpPermission.builder();

View File

@ -42,6 +42,13 @@ public class IpPermissionsTest {
.cidrBlock("a.0.0.0/0").build());
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testAllProtocolInvalidExclusionCidr() {
IpPermissions authorization = IpPermissions.permitAnyProtocol();
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.ALL).fromPort(1).toPort(65535)
.exclusionCidrBlock("a.0.0.0/0").build());
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testAllProtocolInvalidCidrMultiple() {
IpPermissions authorization = IpPermissions.permitAnyProtocol();
@ -49,24 +56,49 @@ public class IpPermissionsTest {
.cidrBlocks(ImmutableSet.of("a.0.0.0/0", "0.0.0.0/0")).build());
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testAllProtocolInvalidExclusionCidrMultiple() {
IpPermissions authorization = IpPermissions.permitAnyProtocol();
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.ALL).fromPort(1).toPort(65535)
.exclusionCidrBlocks(ImmutableSet.of("a.0.0.0/0", "0.0.0.0/0")).build());
}
public void testAllProtocolCidrBound() {
IpPermissions authorization = IpPermissions.permit(IpProtocol.ALL).originatingFromCidrBlock("1.1.1.1/32");
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.ALL).fromPort(1).toPort(65535)
.cidrBlock("1.1.1.1/32").build());
}
public void testAllProtocolExclusionCidrBound() {
IpPermissions authorization = IpPermissions.permit(IpProtocol.ALL).exceptOriginatingFromCidrBlock("1.1.1.1/32");
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.ALL).fromPort(1).toPort(65535)
.exclusionCidrBlock("1.1.1.1/32").build());
}
public void testJustProtocolAndCidr() {
IpPermissions authorization = IpPermissions.permit(IpProtocol.TCP).originatingFromCidrBlock("1.1.1.1/32");
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.TCP).fromPort(1).toPort(65535)
.cidrBlock("1.1.1.1/32").build());
}
public void testJustProtocolAndExcludedCidr() {
IpPermissions authorization = IpPermissions.permit(IpProtocol.TCP).exceptOriginatingFromCidrBlock("1.1.1.1/32");
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.TCP).fromPort(1).toPort(65535)
.exclusionCidrBlock("1.1.1.1/32").build());
}
public void testAnyProtocol() {
IpPermissions authorization = IpPermissions.permitAnyProtocol().originatingFromCidrBlock("1.1.1.1/32");
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.ALL).fromPort(1).toPort(65535)
.cidrBlock("1.1.1.1/32").build());
}
public void testAnyProtocolWithExcludedCidr() {
IpPermissions authorization = IpPermissions.permitAnyProtocol().exceptOriginatingFromCidrBlock("1.1.1.1/32");
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.ALL).fromPort(1).toPort(65535)
.exclusionCidrBlock("1.1.1.1/32").build());
}
public void testMultipleCidrs() {
IpPermissions authorization = IpPermissions.permit(IpProtocol.TCP).originatingFromCidrBlocks(
ImmutableSet.of("1.1.1.1/32", "1.1.1.2/32"));
@ -74,6 +106,13 @@ public class IpPermissionsTest {
.cidrBlocks(ImmutableSet.of("1.1.1.1/32", "1.1.1.2/32")).build());
}
public void testMultipleCidrsExclusions() {
IpPermissions authorization = IpPermissions.permit(IpProtocol.TCP).exceptOriginatingFromCidrBlocks(
ImmutableSet.of("1.1.1.1/32", "1.1.1.2/32"));
assertEquals(authorization, IpPermission.builder().ipProtocol(IpProtocol.TCP).fromPort(1).toPort(65535)
.exclusionCidrBlocks(ImmutableSet.of("1.1.1.1/32", "1.1.1.2/32")).build());
}
public void testProtocolFromAndToPortAndGroupIds() {
IpPermissions authorization = IpPermissions.permit(IpProtocol.UDP).fromPort(11).to(53)
.originatingFromSecurityGroupId("groupId");