Add protocol number support for security group rules (#3736)

Currently while creating ingress/egress rule for a security group,
we can specify only TCP/UDP/ICMP. Sometimes we need to add rules
for different protocol number or rules for all the above three
mentioned protocols.

In this new feature users can specify the protocol number or select
"ALL" option which will apply rules for TCP/UDP/ICMP
This commit is contained in:
Rakesh 2020-01-08 16:13:41 +01:00 committed by Andrija Panic
parent f2708d6636
commit dfd950cab0
5 changed files with 610 additions and 24 deletions

View File

@ -58,7 +58,7 @@ public class AuthorizeSecurityGroupIngressCmd extends BaseAsyncCmd {
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, description = "TCP is default. UDP is the other supported protocol")
@Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, description = "the protocol for the ACL rule. Valid values are TCP/UDP/ICMP/ALL or valid protocol number (see /etc/protocols). ALL is default.")
private String protocol;
@Parameter(name = ApiConstants.START_PORT, type = CommandType.INTEGER, description = "start port for this ingress rule")

View File

@ -1032,7 +1032,18 @@ def add_network_rules(vm_name, vm_id, vm_ip, vm_ip6, signature, seqno, vmMac, ru
action = "ACCEPT"
direction = "-s"
range = str(start) + ':' + str(end)
if start == 0 and end == 0:
dport = ""
else:
dport = " --dport " + str(start) + ":" + str(end)
if protocol != 'all' and protocol != 'icmp' and protocol != 'tcp' and protocol != 'udp':
protocol_all = " -p " + protocol
protocol_state = " "
else:
protocol_all = " -p " + protocol + " -m " + protocol
protocol_state = " -m state --state NEW "
if 'icmp' == protocol:
range = str(start) + '/' + str(end)
if start == -1:
@ -1041,16 +1052,16 @@ def add_network_rules(vm_name, vm_id, vm_ip, vm_ip6, signature, seqno, vmMac, ru
for ip in rule['ipv4']:
if protocol == 'all':
execute('iptables -I ' + vmchain + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
elif protocol != 'icmp':
execute('iptables -I ' + vmchain + ' -p ' + protocol + ' -m ' + protocol + ' --dport ' + range + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
elif protocol == 'icmp':
execute("iptables -I " + vmchain + " -p icmp --icmp-type " + range + " " + direction + " " + ip + " -j " + action)
else:
execute('iptables -I ' + vmchain + ' -p icmp --icmp-type ' + range + ' ' + direction + ' ' + ip + ' -j ' + action)
execute("iptables -I " + vmchain + protocol_all + dport + protocol_state + direction + " " + ip + " -j "+ action)
for ip in rule['ipv6']:
if protocol == 'all':
execute('ip6tables -I ' + vmchain + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
elif 'icmp' != protocol:
execute('ip6tables -I ' + vmchain + ' -p ' + protocol + ' -m ' + protocol + ' --dport ' + range + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
execute("ip6tables -I " + vmchain + protocol_all + dport + protocol_state + direction + " " + ip + " -j "+ action)
else:
# ip6tables does not allow '--icmpv6-type any', allowing all ICMPv6 is done by not allowing a specific type
if range == 'any':

View File

@ -50,6 +50,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
@ -617,10 +618,27 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
}
}
if (!NetUtils.isValidSecurityGroupProto(protocol)) {
throw new InvalidParameterValueException("Invalid protocol " + protocol);
//Validate Protocol
protocol = protocol.trim().toLowerCase();
//Check if protocol is a number
if(StringUtils.isNumeric(protocol)){
int protoNumber = Integer.parseInt(protocol);
// Deal with ICMP(protocol number 1) specially because it need to be paired with icmp type and code
if (protoNumber == 1) {
protocol = "icmp";
icmpCode = -1;
icmpType = -1;
} else if(protoNumber < 0 || protoNumber > 255){
throw new InvalidParameterValueException("Invalid protocol number: " + protoNumber);
}
} else {
//Protocol is not number
//Check for valid protocol strings
if (!NetUtils.isValidSecurityGroupProto(protocol)) {
throw new InvalidParameterValueException("Invalid protocol " + protocol);
}
}
if ("icmp".equalsIgnoreCase(protocol)) {
if (protocol.equals(NetUtils.ICMP_PROTO)) {
if ((icmpType == null) || (icmpCode == null)) {
throw new InvalidParameterValueException("Invalid ICMP type/code specified, icmpType = " + icmpType + ", icmpCode = " + icmpCode);
}
@ -641,7 +659,7 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
}
startPortOrType = 0;
endPortOrCode = 0;
} else {
} else if (protocol.equals(NetUtils.TCP_PROTO) || protocol.equals(NetUtils.UDP_PROTO)) {
if ((startPort == null) || (endPort == null)) {
throw new InvalidParameterValueException("Invalid port range specified, startPort = " + startPort + ", endPort = " + endPort);
}
@ -660,10 +678,13 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
}
startPortOrType = startPort;
endPortOrCode = endPort;
} else {
// in 4.6, the start port and end port are ignored in definition of ProtocolAclRule
// see core/src/com/cloud/agent/resource/virtualnetwork/facade/SetNetworkAclConfigItem.java
startPortOrType = 0;
endPortOrCode = 0;
}
protocol = protocol.toLowerCase();
List<SecurityGroupVO> authorizedGroups = new ArrayList<SecurityGroupVO>();
if (groupList != null) {
Collection userGroupCollection = groupList.values();

View File

@ -0,0 +1,460 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""
Tests protocol number support for security groups
"""
# Import Local Modules
from nose.plugins.attrib import attr
from marvin.cloudstackTestCase import cloudstackTestCase, unittest
from marvin.cloudstackAPI import authorizeSecurityGroupIngress, revokeSecurityGroupIngress, authorizeSecurityGroupEgress, revokeSecurityGroupEgress
from marvin.sshClient import SshClient
from marvin.lib.utils import (validateList,
cleanup_resources,
get_host_credentials)
from marvin.lib.base import (Account,
Host,
Domain,
VirtualMachine,
ServiceOffering,
Zone,
SecurityGroup)
from marvin.lib.common import (get_domain,
get_zone,
get_template,
list_hosts)
import logging
class TestProtocolNumberSecurityGroup(cloudstackTestCase):
@classmethod
def setUpClass(cls):
cls.testClient = super(
TestProtocolNumberSecurityGroup,
cls).getClsTestClient()
cls.apiclient = cls.testClient.getApiClient()
cls.testdata = cls.testClient.getParsedTestDataConfig()
cls.services = cls.testClient.getParsedTestDataConfig()
zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
cls.zone = Zone(zone.__dict__)
cls.template = get_template(cls.apiclient, cls.zone.id)
cls._cleanup = []
if str(cls.zone.securitygroupsenabled) != "True":
sys.exit(1)
cls.logger = logging.getLogger("TestProtocolNumberSecurityGroup")
cls.stream_handler = logging.StreamHandler()
cls.logger.setLevel(logging.DEBUG)
cls.logger.addHandler(cls.stream_handler)
# Get Zone, Domain and templates
cls.domain = get_domain(cls.apiclient)
testClient = super(TestProtocolNumberSecurityGroup, cls).getClsTestClient()
cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
cls.services['mode'] = cls.zone.networktype
# Create new domain, account, network and VM
cls.user_domain = Domain.create(
cls.apiclient,
services=cls.testdata["acl"]["domain2"],
parentdomainid=cls.domain.id)
# Create account
cls.account = Account.create(
cls.apiclient,
cls.testdata["acl"]["accountD2"],
admin=True,
domainid=cls.user_domain.id
)
cls.service_offering = ServiceOffering.create(
cls.apiclient,
cls.testdata["service_offering"]
)
cls.testdata["domainid"] = cls.domain.id
cls.testdata["virtual_machine_userdata"]["zoneid"] = cls.zone.id
cls.testdata["virtual_machine_userdata"]["template"] = cls.template.id
cls._cleanup.append(cls.service_offering)
cls._cleanup.append(cls.account)
cls._cleanup.append(cls.user_domain)
@classmethod
def tearDownClass(self):
try:
cleanup_resources(self.apiclient, self._cleanup)
except Exception as e:
raise Exception("Warning: Exception during cleanup : %s" % e)
return
def setUp(self):
self.apiclient = self.testClient.getApiClient()
self.cleanup = []
return
def tearDown(self):
try:
cleanup_resources(self.apiclient, self.cleanup)
except Exception as e:
raise Exception("Warning: Exception during cleanup : %s" % e)
return
@attr(tags=["advancedsg"], required_hardware="false")
def test_01_add_valid_protocol_number(self):
# Validate the following
#
# 1. Create a security group
# 2. Try to add a new ingress rule by specifying a protocol number
# 3. New rule should be added successfully
# 4. Try to add a new egress rule by specifying a protocol number
# 5. New rule should be added successfully
self.security_group = SecurityGroup.create(
self.apiclient,
self.testdata["security_group"],
account=self.account.name,
domainid=self.account.domainid
)
self.debug("Created security group with ID: %s" % self.security_group.id)
# Add ingress rule
self.createIngressRule("111")
# Add egress rule
self.createEgressRule("111")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 1, 1)
@attr(tags=["advancedsg"], required_hardware="false")
def test_02_add_invalid_protocol_number(self):
# Validate the following
#
# 1. Create a security group
# 2. Try to add a new ingress rule by specifying an invalid (> 255) protocol number
# 3. Exception should be thrown successfully
# 4. Try to add a new egreess rule by specifying an invalid (> 255) protocol number
# 5. Exception should be thrown successfully
self.security_group = SecurityGroup.create(
self.apiclient,
self.testdata["security_group"],
account=self.account.name,
domainid=self.account.domainid
)
self.debug("Created security group with ID: %s" % self.security_group.id)
# Create ingress rule with invalid protocol number. Exception should be thrown
with self.assertRaises(Exception):
self.createIngressRule("555")
# Create egress rule with invalid protocol number. Exception should be thrown
with self.assertRaises(Exception):
self.createEgressRule("555")
@attr(tags=["advancedsg"], required_hardware="false")
def test_03_add_duplicate_protocol_number(self):
# Validate the following
#
# 1. Create a security group
# 2. Try to add a new ingress rule by specifying a protocol number
# 3. Try to add one more ingress rule by specifying the same protocol number
# 4. Exception should be thrown successfully
# 5. Try to add a new egress rule by specifying a protocol number
# 6. Try to add one more egress rule by specifying the same protocol number
# 7. Exception should be thrown successfully
self.security_group = SecurityGroup.create(
self.apiclient,
self.testdata["security_group"],
account=self.account.name,
domainid=self.account.domainid
)
self.debug("Created security group with ID: %s" % self.security_group.id)
# Add ingress rule
self.createIngressRule("111")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 1, 0)
# Try to add another ingress with same protocol number. Exception is thrown
with self.assertRaises(Exception):
self.createIngressRule("111")
# Add egress rule
self.createEgressRule("111")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 1, 1)
# Try to add another ingress with same protocol number. Exception is thrown
with self.assertRaises(Exception):
self.createEgressRule("111")
@attr(tags=["advancedsg"], required_hardware="false")
def test_04_add_duplicate_protocol_number(self):
# Validate the following
#
# 1. Create a security group
# 2. Try to add a new ingress rule by using "all" as the protocol string
# 3. Try to add one more ingress rule by specifying the same protocol
# 4. Exception should be thrown successfully
# 5. Try to add a new egress rule by using "all" as the protocol string
# 6. Try to add one more egress rule by specifying the same protocol
# 7. Exception should be thrown successfully
self.security_group = SecurityGroup.create(
self.apiclient,
self.testdata["security_group"],
account=self.account.name,
domainid=self.account.domainid
)
self.debug("Created security group with ID: %s" % self.security_group.id)
# Add ingress rule
self.createIngressRule("111")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 1, 0)
# Try to add another ingress with same protocol number. Exception is thrown
with self.assertRaises(Exception):
self.createIngressRule("111")
# Add egress rule
self.createEgressRule("111")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 1, 1)
# Try to add another ingress with same protocol number. Exception is thrown
with self.assertRaises(Exception):
self.createEgressRule("111")
@attr(tags=["advancedsg"], required_hardware="false")
def test_05_invalid_protocol_string(self):
# Validate the following
#
# 1. Create a security group
# 2. Try to add ingress rule with invalid protocol name
# 3. Exception should be thrown
# 4. Try to add egressrule with invalid protocol name
# 5. Exception should be thrown
security_group = SecurityGroup.create(
self.apiclient,
self.testdata["security_group"],
account=self.account.name,
domainid=self.account.domainid
)
self.debug("Created security group with ID: %s" % security_group.id)
with self.assertRaises(Exception):
self.createIngressRule("randomprotocol")
with self.assertRaises(Exception):
self.createEgressRule("randomprotocol")
@attr(tags=["advancedsg"])
def test_06_create_virtual_machine(self):
# Validate the following
#
# 1. Create a security group
# 2. Create a virtual machine
# 3. Try to add a new ingress rule
# 4. Check if ingress rule is applied successfully on host
# 5. Throw exception if it's not applied
# 6. Try to add a new egress rule
# 7. Check if egress rule is applied successfully on host
# 8. Throw exception if it's not applied
self.security_group = SecurityGroup.create(
self.apiclient,
self.testdata["security_group"],
account=self.account.name,
domainid=self.account.domainid
)
self.virtual_machine = VirtualMachine.create(
self.apiclient,
self.testdata["virtual_machine_userdata"],
accountid=self.account.name,
domainid=self.account.domainid,
serviceofferingid=self.service_offering.id,
securitygroupids=[self.security_group.id]
)
# Get the virtual machine
virtial_machine = VirtualMachine.list(
self.apiclient,
id=self.virtual_machine.id
)
vm = virtial_machine[0]
# get the host on which the vm is running
hosts = list_hosts(
self.apiclient,
id=vm.hostid
)
host = hosts[0]
if host.hypervisor.lower() not in "kvm":
return
host.user, host.passwd = get_host_credentials(self.config, host.ipaddress)
# Add ingress rule
self.createIngressRule("tcp", "1.1.1.1/32")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 1, 0)
# Check if the ingress rule if applied successfully on host
rule = "-A %s -s 1.1.1.1/32 -p tcp -m tcp --dport 1:65535 -m state --state NEW -j ACCEPT" % vm.instancename
self.verify_rule_on_host(host.ipaddress, host.user, host.passwd, rule)
# Add ingress rule
self.createIngressRule("udp", "2.2.2.2/32")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 2, 0)
# Check if the ingress rule if applied successfully on host
rule = "-A %s -s 2.2.2.2/32 -p udp -m udp --dport 1:65535 -m state --state NEW -j ACCEPT" % vm.instancename
self.verify_rule_on_host(host.ipaddress, host.user, host.passwd, rule)
# Add ingress rule
self.createIngressRule("icmp", "3.3.3.3/32")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 3, 0)
# Check if the ingress rule if applied successfully on host
rule = "-A %s -s 3.3.3.3/32 -p icmp -m icmp --icmp-type any -j ACCEPT" % vm.instancename
self.verify_rule_on_host(host.ipaddress, host.user, host.passwd, rule)
# Add ingress rule
self.createIngressRule("all", "4.4.4.4/32")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 4, 0)
# Check if the ingress rule if applied successfully on host
rule = "-A %s -s 4.4.4.4/32 -m state --state NEW -j ACCEPT" % vm.instancename
self.verify_rule_on_host(host.ipaddress, host.user, host.passwd, rule)
# Add ingress rule
self.createIngressRule("47", "5.5.5.5/32")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 5, 0)
# Check if the ingress rule if applied successfully on host
rule = "-A %s -s 5.5.5.5/32 -p gre -j ACCEPT" % vm.instancename
self.verify_rule_on_host(host.ipaddress, host.user, host.passwd, rule)
# Add egress rule
self.createEgressRule("tcp", "11.11.11.11/32")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 5, 1)
# Check if the egress rule if applied successfully on host
rule = "-A %s-eg -d 11.11.11.11/32 -p tcp -m tcp --dport 1:65535 -m state --state NEW -j RETURN" % vm.instancename
self.verify_rule_on_host(host.ipaddress, host.user, host.passwd, rule)
# Add egress rule
self.createEgressRule("udp", "12.12.12.12/32")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 5, 2)
# Check if the egress rule if applied successfully on host
rule = "-A %s-eg -d 12.12.12.12/32 -p udp -m udp --dport 1:65535 -m state --state NEW -j RETURN" % vm.instancename
self.verify_rule_on_host(host.ipaddress, host.user, host.passwd, rule)
# Add egress rule
self.createEgressRule("icmp", "13.13.13.13/32")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 5, 3)
# Check if the egress rule if applied successfully on host
rule = "-A %s-eg -d 13.13.13.13/32 -p icmp -m icmp --icmp-type any -j RETURN" % vm.instancename
self.verify_rule_on_host(host.ipaddress, host.user, host.passwd, rule)
# Add egress rule
self.createEgressRule("all", "14.14.14.14/32")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 5, 4)
# Check if the egress rule if applied successfully on host
rule = "-A %s-eg -d 14.14.14.14/32 -m state --state NEW -j RETURN" % vm.instancename
self.verify_rule_on_host(host.ipaddress, host.user, host.passwd, rule)
# Add egress rule
self.createEgressRule("47", "15.15.15.15/32")
# verify number of ingress rules and egress rules
self.verify_security_group_rules(self.security_group.id, 5, 5)
# Check if the egress rule if applied successfully on host
rule = "-A %s-eg -d 15.15.15.15/32 -p gre -j RETURN" % vm.instancename
self.verify_rule_on_host(host.ipaddress, host.user, host.passwd, rule)
def createIngressRule(self, protocol, cidrlist=None):
cmd = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd()
cmd.account=self.account.name
cmd.domainid=self.account.domainid
cmd.securitygroupid=self.security_group.id
cmd.cidrlist="99.99.99.99/32"
if cidrlist:
cmd.cidrlist=cidrlist
cmd.protocol=protocol
if protocol == "tcp" or protocol == "udp":
cmd.startport = 1
cmd.endport = 65535
elif protocol == "icmp":
cmd.icmptype = -1
cmd.icmpcode = -1
self.apiclient.authorizeSecurityGroupIngress(cmd)
cmd = None
def createEgressRule(self, protocol, cidrlist=None):
cmd = authorizeSecurityGroupEgress.authorizeSecurityGroupEgressCmd()
cmd.account=self.account.name
cmd.domainid=self.account.domainid
cmd.securitygroupid=self.security_group.id
cmd.cidrlist="88.88.88.88/32"
if cidrlist:
cmd.cidrlist=cidrlist
cmd.protocol=protocol
if protocol == "tcp" or protocol == "udp":
cmd.startport = 1
cmd.endport = 65535
elif protocol == "icmp":
cmd.icmptype = -1
cmd.icmpcode = -1
self.apiclient.authorizeSecurityGroupEgress(cmd)
cmd = None
def verify_security_group_rules(self, securitygroupid, numIngress, numEgress):
security_groups = SecurityGroup.list(
self.apiclient,
account=self.account.name,
domainid=self.account.domainid,
id=securitygroupid
)
ingressrule = security_groups[0].ingressrule
if len(ingressrule) != numIngress:
raise Exception("Failed to verify ingress rule for security group %s" % security_groups[0].name)
egressrule = security_groups[0].egressrule
if len(egressrule) != numEgress:
raise Exception("Failed to verify egress rule for security group %s" % security_groups[0].name)
def verify_rule_on_host(self, ipaddress, user, password, rule):
self.logger.debug("Verifying rule '%s' in host %s" % (rule, ipaddress))
try:
ssh = SshClient(ipaddress, 22, user, password)
result = ssh.execute("iptables-save |grep \"\\%s\"" % rule)
if len(result) == 0 or result[0] != rule:
raise Exception("Unable to apply security group rule")
except KeyError:
self.skipTest(
"Provide a marvin config file with host credentials to run %s" % self._testMethodName)

View File

@ -41,6 +41,10 @@
elemData.endport = icmpcode;
}
if (elemData.protocol != 'tcp' && elemData.protocol != 'udp' && elemData.protocol != 'icmp') {
elemData.startport = 'all';
elemData.endport = 'all';
}
return elemData;
};
@ -4581,7 +4585,8 @@
var $otherFields = $inputs.filter(function() {
var name = $(this).attr('rel');
return name != 'icmptype' &&
return name != 'protocolnumber' &&
name != 'icmptype' &&
name != 'icmpcode' &&
name != 'protocol' &&
name != 'add-rule' &&
@ -4590,12 +4595,35 @@
name != 'securitygroup';
});
if ($(this).val() == 'icmp') {
$icmpFields.show();
$otherFields.hide();
} else {
$portFields = $inputs.filter(function() {
var name = $(this).attr('rel');
return $.inArray(name, [
'startport',
'endport'
]) > -1;
});
$protocolFields = $inputs.filter(function() {
var name = $(this).attr('rel');
return $.inArray(name, ['protocolnumber']) > -1;
});
if ($(this).val() == 'protocolnumber') {
$icmpFields.hide();
$portFields.hide();
$protocolFields.show();
} else if ($(this).val() == 'icmp') {
$icmpFields.show();
$protocolFields.hide();
$portFields.hide();
} else if ($(this).val() == 'all') {
$portFields.hide();
$icmpFields.hide();
$protocolFields.hide();
} else {
$otherFields.show();
$icmpFields.hide();
$protocolFields.hide();
}
});
@ -4609,10 +4637,22 @@
}, {
name: 'icmp',
description: 'ICMP'
}, {
name: 'all',
description: 'ALL'
}, {
name: 'protocolnumber',
description: 'Protocol Number'
}]
});
}
},
'protocolnumber': {
label: 'label.protocol.number',
edit: true,
isHidden: true,
isEditable: true
},
'startport': {
edit: true,
label: 'label.start.port',
@ -4663,11 +4703,20 @@
action: function(args) {
var data = {
securitygroupid: args.context.securityGroups[0].id,
protocol: args.data.protocol,
domainid: args.context.securityGroups[0].domainid,
account: args.context.securityGroups[0].account
};
if (args.data.protocol == 'protocolnumber') {
$.extend(data, {
protocol: args.data.protocolnumber
});
} else {
$.extend(data, {
protocol: args.data.protocol
});
}
if (args.data.icmptype && args.data.icmpcode) { // ICMP
$.extend(data, {
icmptype: args.data.icmptype,
@ -4791,7 +4840,8 @@
var $otherFields = $inputs.filter(function() {
var name = $(this).attr('rel');
return name != 'icmptype' &&
return name != 'protocolnumber' &&
name != 'icmptype' &&
name != 'icmpcode' &&
name != 'protocol' &&
name != 'add-rule' &&
@ -4800,12 +4850,35 @@
name != 'securitygroup';
});
if ($(this).val() == 'icmp') {
$icmpFields.show();
$otherFields.hide();
} else {
$portFields = $inputs.filter(function() {
var name = $(this).attr('rel');
return $.inArray(name, [
'startport',
'endport'
]) > -1;
});
$protocolFields = $inputs.filter(function() {
var name = $(this).attr('rel');
return $.inArray(name, ['protocolnumber']) > -1;
});
if ($(this).val() == 'protocolnumber') {
$icmpFields.hide();
$portFields.hide();
$protocolFields.show();
} else if ($(this).val() == 'icmp') {
$icmpFields.show();
$protocolFields.hide();
$portFields.hide();
} else if ($(this).val() == 'all') {
$portFields.hide();
$icmpFields.hide();
$protocolFields.hide();
} else {
$otherFields.show();
$icmpFields.hide();
$protocolFields.hide();
}
});
@ -4819,10 +4892,22 @@
}, {
name: 'icmp',
description: 'ICMP'
}, {
name: 'all',
description: 'ALL'
}, {
name: 'protocolnumber',
description: 'Protocol Number'
}]
});
}
},
'protocolnumber': {
label: 'label.protocol.number',
edit: true,
isHidden: true,
isEditable: true
},
'startport': {
edit: true,
label: 'label.start.port',
@ -4873,11 +4958,20 @@
action: function(args) {
var data = {
securitygroupid: args.context.securityGroups[0].id,
protocol: args.data.protocol,
domainid: args.context.securityGroups[0].domainid,
account: args.context.securityGroups[0].account
};
if (args.data.protocol == 'protocolnumber') {
$.extend(data, {
protocol: args.data.protocolnumber
});
} else {
$.extend(data, {
protocol: args.data.protocol
});
}
if (args.data.icmptype && args.data.icmpcode) { // ICMP
$.extend(data, {
icmptype: args.data.icmptype,