class CreateSubnet(forms.SelfHandlingForm): network_name = forms.CharField(label=_("Network Name"), required=False, widget=forms.TextInput( attrs={'readonly': 'readonly'})) network_id = forms.CharField(label=_("Network ID"), widget=forms.TextInput( attrs={'readonly': 'readonly'})) name = forms.CharField(max_length=255, label=_("Name"), required=False) cidr = fields.IPField(label=_("Network Address"), required=True, initial="", help_text=_("Network address in CIDR format " "(e.g. 192.168.0.0/24)"), version=fields.IPv4 | fields.IPv6, mask=True) ip_version = forms.ChoiceField(choices=[(4, 'IPv4'), (6, 'IPv6')], label=_("IP Version")) gateway_ip = fields.IPField(label=_("Gateway IP"), required=False, initial="", help_text=_("IP address of Gateway " "(e.g. 192.168.0.1)"), version=fields.IPv4 | fields.IPv6, mask=False) failure_url = 'horizon:project:networks:detail' def clean(self): cleaned_data = super(CreateSubnet, self).clean() cidr = cleaned_data.get('cidr') ip_version = int(cleaned_data.get('ip_version')) gateway_ip = cleaned_data.get('gateway_ip') if cidr: if netaddr.IPNetwork(cidr).version is not ip_version: msg = _('Network Address and IP version are inconsistent.') raise forms.ValidationError(msg) if gateway_ip: if netaddr.IPAddress(gateway_ip).version is not ip_version: msg = _('Gateway IP and IP version are inconsistent.') raise forms.ValidationError(msg) return cleaned_data def handle(self, request, data): try: LOG.debug('params = %s' % data) data['ip_version'] = int(data['ip_version']) if not data['gateway_ip']: del data['gateway_ip'] subnet = api.quantum.subnet_create(request, **data) msg = _('Subnet %s was successfully created.') % data['cidr'] LOG.debug(msg) messages.success(request, msg) return subnet except Exception: msg = _('Failed to create subnet %s') % data['cidr'] LOG.info(msg) redirect = reverse(self.failure_url, args=[data['network_id']]) exceptions.handle(request, msg, redirect=redirect)
def test_validate_IPs(self): GOOD_IPS_V4 = ("0.0.0.0", "10.144.11.107", "169.144.11.107", "172.100.11.107", "255.255.255.255", "0.1.2.3") GOOD_IPS_V6 = ("", "::ffff:0:0", "2001:0db8::1428:57ab", "FEC0::", "fe80::204:61ff:254.157.241.86", "fe80::204:61ff:254.157.241.86", "2001:0DB8::CD30:0:0:0:0") BAD_IPS_V4 = ("1111:2222:3333:4444:::", "::2222:3333:4444:5555:6666:7777:8888:", ":1111:2222:3333:4444::6666:1.2.3.4", "1111:2222::4444:5555:6666::8888", "1111:2222::4444:5555:6666:8888/", "1111:2222::4444:5555:6666::8888/130", "127.0.0.1/", "127.0.0.1/33", "127.0.0.1/-1") BAD_IPS_V6 = ("1111:2222:3333:4444:::", "::2222:3333:4444:5555:6666:7777:8888:", ":1111:2222:3333:4444::6666:1.2.3.4", "1111:2222::4444:5555:6666::8888", "1111:2222::4444:5555:6666:8888/", "1111:2222::4444:5555:6666::8888/130") ipv4 = fields.IPField(required=True, version=fields.IPv4) ipv6 = fields.IPField(required=False, version=fields.IPv6) ipmixed = fields.IPField(required=False, version=fields.IPv4 | fields.IPv6) for ip_addr in GOOD_IPS_V4: self.assertIsNone(ipv4.validate(ip_addr)) self.assertIsNone(ipmixed.validate(ip_addr)) for ip_addr in GOOD_IPS_V6: self.assertIsNone(ipv6.validate(ip_addr)) self.assertIsNone(ipmixed.validate(ip_addr)) for ip_addr in BAD_IPS_V4: self.assertRaises(ValidationError, ipv4.validate, ip_addr) self.assertRaises(ValidationError, ipmixed.validate, ip_addr) for ip_addr in BAD_IPS_V6: self.assertRaises(ValidationError, ipv6.validate, ip_addr) self.assertRaises(ValidationError, ipmixed.validate, ip_addr) self.assertRaises(ValidationError, ipv4.validate, "") # required=True iprange = fields.IPField(required=False, mask=True, mask_range_from=10, version=fields.IPv4 | fields.IPv6) self.assertRaises(ValidationError, iprange.validate, "fe80::204:61ff:254.157.241.86/6") self.assertRaises(ValidationError, iprange.validate, "169.144.11.107/8") self.assertIsNone(iprange.validate("fe80::204:61ff:254.157.241.86/36")) self.assertIsNone(iprange.validate("169.144.11.107/18"))
class AddRuleAction(workflows.Action): name = forms.CharField( max_length=80, label=_("Name"), required=False) description = forms.CharField( max_length=80, label=_("Description"), required=False) protocol = forms.ChoiceField( label=_("Protocol"), choices=[('tcp', _('TCP')), ('udp', _('UDP')), ('icmp', _('ICMP')), ('any', _('ANY'))],) action = forms.ChoiceField( label=_("Action"), choices=[('allow', _('ALLOW')), ('deny', _('DENY'))],) source_ip_address = fields.IPField( label=_("Source IP Address/Subnet"), version=fields.IPv4 | fields.IPv6, required=False, mask=True) destination_ip_address = fields.IPField( label=_("Destination IP Address/Subnet"), version=fields.IPv4 | fields.IPv6, required=False, mask=True) source_port = forms.CharField( max_length=80, label=_("Source Port/Port Range"), required=False, validators=[port_validator]) destination_port = forms.CharField( max_length=80, label=_("Destination Port/Port Range"), required=False, validators=[port_validator]) shared = forms.BooleanField( label=_("Shared"), initial=False, required=False) enabled = forms.BooleanField( label=_("Enabled"), initial=True, required=False) def __init__(self, request, *args, **kwargs): super(AddRuleAction, self).__init__(request, *args, **kwargs) class Meta: name = _("AddRule") permissions = ('openstack.services.network',) help_text = _("Create a firewall rule.\n\n" "Protocol and action must be specified. " "Other fields are optional.")
class UpdateSubnetInfoAction(CreateSubnetInfoAction): cidr = fields.IPField( label=_("Network Address"), required=False, initial="", widget=forms.TextInput(attrs={'readonly': 'readonly'}), help_text=_("Network address in CIDR format " "(e.g. 192.168.0.0/24)"), version=fields.IPv4 | fields.IPv6, mask=True) # NOTE(amotoki): When 'disabled' attribute is set for the ChoiceField # and ValidationError is raised for POST request, the initial value of # the ip_version ChoiceField is not set in the re-displayed form # As a result, 'IPv4' is displayed even when IPv6 is used if # ValidationError is detected. In addition 'required=True' check complains # when re-POST since the value of the ChoiceField is not set. # Thus now I use HiddenInput for the ip_version ChoiceField as a work # around. ip_version = forms.ChoiceField( choices=[(4, 'IPv4'), (6, 'IPv6')], #widget=forms.Select( # attrs={'disabled': 'disabled'}), widget=forms.HiddenInput(), label=_("IP Version")) gateway_ip = fields.IPField( label=_("Gateway IP (optional)"), required=False, initial="", help_text=_("IP address of Gateway (e.g. 192.168.0.254). " "You need to specify an explicit address " "to set the gateway. " "If you want to use no gateway, " "check 'Disable Gateway' below."), version=fields.IPv4 | fields.IPv6, mask=False) no_gateway = forms.BooleanField(label=_("Disable Gateway"), initial=False, required=False) class Meta: name = ("Subnet") help_text = _('You can update a subnet associated with the ' 'network. Advanced configuration are available ' 'at "Subnet Detail" tab.') def clean(self): cleaned_data = workflows.Action.clean(self) self._check_subnet_data(cleaned_data, is_create=False) return cleaned_data
class CreateSubnetInfoAction(workflows.Action): with_subnet = forms.BooleanField(label=_("Create Subnet"), initial=True, required=False) subnet_name = forms.CharField(max_length=255, label=_("Subnet Name (optional)"), required=False) cidr = fields.IPField(label=_("Network Address"), required=False, initial="", help_text=_("Network address in CIDR format " "(e.g. 192.168.0.0/24)"), version=fields.IPv4 | fields.IPv6, mask=True) ip_version = forms.ChoiceField(choices=[(4, 'IPv4'), (6, 'IPv6')], label=_("IP Version")) gateway_ip = fields.IPField(label=_("Gateway IP (optional)"), required=False, initial="", help_text=_("IP address of Gateway " "(e.g. 192.168.0.1)"), version=fields.IPv4 | fields.IPv6, mask=False) class Meta: name = ("Subnet") help_text = _('You can create a subnet associated with the new ' 'network, in which case "Network Address" must be ' 'specified. If you wish to create a network WITHOUT a ' 'subnet, uncheck the "Create Subnet" checkbox.') def clean(self): cleaned_data = super(CreateSubnetInfoAction, self).clean() with_subnet = cleaned_data.get('with_subnet') cidr = cleaned_data.get('cidr') ip_version = int(cleaned_data.get('ip_version')) gateway_ip = cleaned_data.get('gateway_ip') if with_subnet and not cidr: msg = _('Specify "Network Address" or ' 'clear "Create Subnet" checkbox.') raise forms.ValidationError(msg) if cidr: if netaddr.IPNetwork(cidr).version is not ip_version: msg = _('Network Address and IP version are inconsistent.') raise forms.ValidationError(msg) if gateway_ip: if netaddr.IPAddress(gateway_ip).version is not ip_version: msg = _('Gateway IP and IP version are inconsistent.') raise forms.ValidationError(msg) return cleaned_data
def test_validate_ipv6_cidr(self): GOOD_CIDRS = ("::ffff:0:0/56", "2001:0db8::1428:57ab/17", "FEC0::/10", "fe80::204:61ff:254.157.241.86/4", "fe80::204:61ff:254.157.241.86/0", "2001:0DB8::CD30:0:0:0:0/60", "2001:0DB8::CD30:0/90", "::1/128") BAD_CIDRS = ("1111:2222:3333:4444:::/", "::2222:3333:4444:5555:6666:7777:8888:\\", ":1111:2222:3333:4444::6666:1.2.3.4/1000", "1111:2222::4444:5555:6666::8888@", "1111:2222::4444:5555:6666:8888/", "::ffff:0:0/129", "1.2.3.4:1111:2222::5555//22", "fe80::204:61ff:254.157.241.86/200", # some valid IPv4 addresses "10.144.11.107/4", "255.255.255.255/0", "0.1.2.3/16") ip = fields.IPField(mask=True, version=fields.IPv6) for cidr in GOOD_CIDRS: self.assertIsNone(ip.validate(cidr)) for cidr in BAD_CIDRS: self.assertRaises(ValidationError, ip.validate, cidr)
def test_validate_ipv4_cidr(self): GOOD_CIDRS = ( "192.168.1.1/16", "192.0.0.1/17", "0.0.0.0/16", "10.144.11.107/4", "255.255.255.255/0", "0.1.2.3/16", "0.0.0.0/32", # short form "128.0/16", "128/4") BAD_CIDRS = ( "255.255.255.256\\", "256.255.255.255$", "1.2.3.4.5/41", "0.0.0.0/99", "127.0.0.1/", "127.0.0.1/33", "127.0.0.1/-1", "127.0.0.1/100", # some valid IPv6 addresses "fe80::204:61ff:254.157.241.86/4", "fe80::204:61ff:254.157.241.86/0", "2001:0DB8::CD30:0:0:0:0/60", "2001:0DB8::CD30:0/90") ip = fields.IPField(mask=True, version=fields.IPv4) for cidr in GOOD_CIDRS: self.assertIsNone(ip.validate(cidr)) for cidr in BAD_CIDRS: self.assertRaises(ValidationError, ip.validate, cidr)
def test_validate_mixed_cidr(self): GOOD_CIDRS = ( "::ffff:0:0/56", "2001:0db8::1428:57ab/17", "FEC0::/10", "fe80::204:61ff:254.157.241.86/4", "fe80::204:61ff:254.157.241.86/0", "2001:0DB8::CD30:0:0:0:0/60", "0.0.0.0/16", "10.144.11.107/4", "255.255.255.255/0", "0.1.2.3/16", # short form "128.0/16", "10/4") BAD_CIDRS = ("1111:2222:3333:4444::://", "::2222:3333:4444:5555:6666:7777:8888:", ":1111:2222:3333:4444::6666:1.2.3.4/1/1", "1111:2222::4444:5555:6666::8888\\2", "1111:2222::4444:5555:6666:8888/", "1111:2222::4444:5555:6666::8888/130", "127.0.0.1/", "127.0.0.1/33", "127.0.0.1/-1") ip = fields.IPField(mask=True, version=fields.IPv4 | fields.IPv6) for cidr in GOOD_CIDRS: self.assertIsNone(ip.validate(cidr)) for cidr in BAD_CIDRS: self.assertRaises(ValidationError, ip.validate, cidr)
class AddVipAction(workflows.Action): name = forms.CharField(max_length=80, label=_("Name")) description = forms.CharField( initial="", required=False, max_length=80, label=_("Description")) floatip_address = forms.ChoiceField( label=_("Vip Address from Floating IPs"), widget=forms.Select(attrs={'disabled': 'disabled'}), required=False) other_address = fields.IPField(required=False, initial="", version=fields.IPv4, mask=False) protocol_port = forms.CharField(max_length=80, label=_("Protocol Port")) protocol = forms.ChoiceField(label=_("Protocol")) session_persistence = forms.ChoiceField( required=False, initial={}, label=_("Session Persistence")) cookie_name = forms.CharField( initial="", required=False, max_length=80, label=_("Cookie Name"), help_text=_("Required for APP_COOKIE persistence;" " Ignored otherwise.")) connection_limit = forms.CharField( max_length=80, label=_("Connection Limit")) admin_state_up = forms.BooleanField( label=_("Admin State"), initial=True, required=False) def __init__(self, request, *args, **kwargs): super(AddVipAction, self).__init__(request, *args, **kwargs) self.fields['other_address'].label = _("Specify a free IP address" " from %s" % args[0]['subnet']) protocol_choices = [('', _("Select a Protocol"))] protocol_choices.append(('HTTP', 'HTTP')) protocol_choices.append(('HTTPS', 'HTTPS')) self.fields['protocol'].choices = protocol_choices session_persistence_choices = [('', _("Set Session Persistence"))] for mode in ('SOURCE_IP', 'HTTP_COOKIE', 'APP_COOKIE'): session_persistence_choices.append((mode, mode)) self.fields[ 'session_persistence'].choices = session_persistence_choices floatip_address_choices = [('', _("Currently Not Supported"))] self.fields['floatip_address'].choices = floatip_address_choices class Meta: name = _("AddVip") permissions = ('openstack.services.network',) help_text = _("Create a vip (virtual IP) for this pool. " "Assign a name and description for the vip. " "Specify an IP address and port for the vip. " "Choose the protocol and session persistence " "method for the vip." "Specify the max connections allowed. " "Admin State is UP (checked) by default.")
class CreateSiteDetailAction(workflows.Action): with_gw = forms.BooleanField( label=_("Add your Enterprise Gateway to this VPN"), initial=True, required=False) #LGCHOICES = (('Provider_AZ1_GW1', 'Cloud Provider Avail. Zone 1 - Gateway 1'), ('Provider_AZ2_GW1', 'Cloud Provider Avail. Zone 2 - Gateway 1'), ('Provider_AZ2_GW2', 'Cloud Provider Avail. Zone 2 - Gateway 2'), ('new', 'Add a New Gateway')) RGCHOICES = (('GW1_Data_Center_San_Jose_B', 'Enterprise Data Center in San Jose B - Gateway 1'), ('GW1_Data_Center_Jorvas', 'Enterprise Data Center in Jorvas - Gateway 1'), ('new', 'Add a New Gateway')) # lgwchoice = forms.ChoiceField(required=True, label='Add a Provider Gateway', choices=LGCHOICES) rgwchoice = forms.ChoiceField(required=True, label='PreConfigured Enterprise Gateway', choices=RGCHOICES) gw_name = forms.CharField( max_length=255, label= _("If your Enterprise Gateway (managed by a VPN agent with chosen VPN type) does not appear, add it:" ), help_text=_("Enterprise Gateway Name. This field is " "optional."), required=False) gw_endpoint = fields.IPField( label=_("Enterprise Gateway Mgmt IP address (default mgmt port)"), required=False, initial="10.126.70.70", help_text=_( "Enterprise Gateway Network address in IPv4 or IPv6 address format " "(e.g. 192.168.0.0)"), version=fields.IPv4 | fields.IPv6, mask=False) auto_gw = forms.BooleanField( label=_("AutoDiscover/Choose GWs in Cloud Provider Avail. Zone 1"), initial=True, required=False) class Meta: name = ("Provider and Enterprise Gateways") help_text = _( 'You can specify the Provider and Enterprise Gateways in Provider and Enterprise Sites resp. to add to this VPN.' ) def clean(self): cleaned_data = super(CreateSiteDetailAction, self).clean() return cleaned_data
class BaseNetworkAliasForm(forms.SelfHandlingForm): id = forms.CharField( label=_("Id"), widget=forms.HiddenInput, required=False) name = forms.CharField(label=_("Name"), max_length=255) cidr = fields.IPField(label=_("Network Address"), required=False, initial="", help_text=_("Network address in CIDR format " "(e.g. 192.168.0.0/24)"), version=fields.IPv4 | fields.IPv6, mask=True) group = forms.ChoiceField(label=_("Adddress Group"), choices=()) def __init__(self, *args, **kwargs): super(BaseNetworkAliasForm, self).__init__(*args, **kwargs) group = get_address_groups(self.request) self.fields['group'] = forms.ChoiceField(choices=group)
class UpdateSubnet(forms.SelfHandlingForm): network_id = forms.CharField(widget=forms.HiddenInput()) subnet_id = forms.CharField(widget=forms.HiddenInput()) cidr = forms.CharField(widget=forms.HiddenInput()) ip_version = forms.CharField(widget=forms.HiddenInput()) name = forms.CharField(max_length=255, label=_("Name"), required=False) gateway_ip = fields.IPField(label=_("Gateway IP"), required=True, initial="", help_text=_("IP address of Gateway " "(e.g. 192.168.0.1)"), version=fields.IPv4 | fields.IPv6, mask=False) failure_url = 'horizon:project:networks:detail' def clean(self): cleaned_data = super(UpdateSubnet, self).clean() ip_version = int(cleaned_data.get('ip_version')) gateway_ip = cleaned_data.get('gateway_ip') if gateway_ip: if netaddr.IPAddress(gateway_ip).version is not ip_version: msg = _('Gateway IP and IP version are inconsistent.') raise forms.ValidationError(msg) return cleaned_data def handle(self, request, data): try: LOG.debug('params = %s' % data) params = {'name': data['name']} params['gateway_ip'] = data['gateway_ip'] subnet = api.quantum.subnet_modify(request, data['subnet_id'], name=data['name'], gateway_ip=data['gateway_ip']) msg = _('Subnet %s was successfully updated.') % data['cidr'] LOG.debug(msg) messages.success(request, msg) return subnet except Exception: msg = _('Failed to update subnet %s') % data['cidr'] LOG.info(msg) redirect = reverse(self.failure_url, args=[data['network_id']]) exceptions.handle(request, msg, redirect=redirect)
class AddRule(forms.SelfHandlingForm): id = forms.CharField(widget=forms.HiddenInput()) rule_menu = forms.ChoiceField(label=_('Rule'), widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'rule_menu'})) # "direction" field is enabled only when custom mode. # It is because most common rules in local_settings.py is meaningful # when its direction is 'ingress'. direction = forms.ChoiceField( label=_('Direction'), required=False, widget=forms.Select(attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-tcp': _('Direction'), 'data-rule_menu-udp': _('Direction'), 'data-rule_menu-icmp': _('Direction'), 'data-rule_menu-custom': _('Direction'), 'data-rule_menu-all_tcp': _('Direction'), 'data-rule_menu-all_udp': _('Direction'), 'data-rule_menu-all_icmp': _('Direction'), })) ip_protocol = forms.IntegerField( label=_('IP Protocol'), required=False, help_text=_("Enter an integer value between 0 and 255 " "(or -1 which means wildcard)."), validators=[validate_ip_protocol], widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-custom': _('IP Protocol')})) port_or_range = forms.ChoiceField( label=_('Open Port'), choices=[('port', _('Port')), ('range', _('Port Range'))], widget=forms.Select(attrs={ 'class': 'switchable switched', 'data-slug': 'range', 'data-switch-on': 'rule_menu', 'data-rule_menu-tcp': _('Open Port'), 'data-rule_menu-udp': _('Open Port')})) port = forms.IntegerField(label=_("Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'range', 'data-range-port': _('Port')}), validators=[validate_port_range]) from_port = forms.IntegerField(label=_("From Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'range', 'data-range-range': _('From Port')}), validators=[validate_port_range]) to_port = forms.IntegerField(label=_("To Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'range', 'data-range-range': _('To Port')}), validators=[validate_port_range]) icmp_type = forms.IntegerField(label=_("Type"), required=False, help_text=_("Enter a value for ICMP type " "in the range (-1: 255)"), widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-icmp': _('Type')}), validators=[validate_port_range]) icmp_code = forms.IntegerField(label=_("Code"), required=False, help_text=_("Enter a value for ICMP code " "in the range (-1: 255)"), widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'rule_menu', 'data-rule_menu-icmp': _('Code')}), validators=[validate_port_range]) remote = forms.ChoiceField(label=_('Remote'), choices=[('cidr', _('CIDR')), ('sg', _('Security Group'))], help_text=_('To specify an allowed IP ' 'range, select "CIDR". To ' 'allow access from all ' 'members of another security ' 'group select "Security ' 'Group".'), widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'remote'})) cidr = fields.IPField(label=_("CIDR"), required=False, initial="0.0.0.0/0", help_text=_("Classless Inter-Domain Routing " "(e.g. 192.168.0.0/24)"), version=fields.IPv4 | fields.IPv6, mask=True, widget=forms.TextInput( attrs={'class': 'switched', 'data-switch-on': 'remote', 'data-remote-cidr': _('CIDR')})) security_group = forms.ChoiceField(label=_('Security Group'), required=False, widget=forms.Select(attrs={ 'class': 'switched', 'data-switch-on': 'remote', 'data-remote-sg': _('Security ' 'Group')})) # When cidr is used ethertype is determined from IP version of cidr. # When source group, ethertype needs to be specified explicitly. ethertype = forms.ChoiceField(label=_('Ether Type'), required=False, choices=[('IPv4', _('IPv4')), ('IPv6', _('IPv6'))], widget=forms.Select(attrs={ 'class': 'switched', 'data-slug': 'ethertype', 'data-switch-on': 'remote', 'data-remote-sg': _('Ether Type')})) def __init__(self, *args, **kwargs): sg_list = kwargs.pop('sg_list', []) super(AddRule, self).__init__(*args, **kwargs) # Determine if there are security groups available for the # remote group option; add the choices and enable the option if so. if sg_list: security_groups_choices = sg_list else: security_groups_choices = [("", _("No security groups available"))] self.fields['security_group'].choices = security_groups_choices backend = api.network.security_group_backend(self.request) rules_dict = getattr(settings, 'SECURITY_GROUP_RULES', []) common_rules = [(k, _(rules_dict[k]['name'])) for k in rules_dict if rules_dict[k].get('backend', backend) == backend] common_rules.sort() custom_rules = [('tcp', _('Custom TCP Rule')), ('udp', _('Custom UDP Rule')), ('icmp', _('Custom ICMP Rule'))] if backend == 'neutron': custom_rules.append(('custom', _('Other Protocol'))) self.fields['rule_menu'].choices = custom_rules + common_rules self.rules = rules_dict if backend == 'neutron': self.fields['direction'].choices = [('ingress', _('Ingress')), ('egress', _('Egress'))] else: # direction and ethertype are not supported in Nova secgroup. self.fields['direction'].widget = forms.HiddenInput() self.fields['ethertype'].widget = forms.HiddenInput() # ip_protocol field is to specify arbitrary protocol number # and it is available only for neutron security group. self.fields['ip_protocol'].widget = forms.HiddenInput() def clean(self): cleaned_data = super(AddRule, self).clean() rule_menu = cleaned_data.get('rule_menu') port_or_range = cleaned_data.get("port_or_range") remote = cleaned_data.get("remote") icmp_type = cleaned_data.get("icmp_type", None) icmp_code = cleaned_data.get("icmp_code", None) from_port = cleaned_data.get("from_port", None) to_port = cleaned_data.get("to_port", None) port = cleaned_data.get("port", None) if rule_menu == 'icmp': cleaned_data['ip_protocol'] = rule_menu if icmp_type is None: msg = _('The ICMP type is invalid.') raise ValidationError(msg) if icmp_code is None: msg = _('The ICMP code is invalid.') raise ValidationError(msg) if icmp_type not in xrange(-1, 256): msg = _('The ICMP type not in range (-1, 255)') raise ValidationError(msg) if icmp_code not in xrange(-1, 256): msg = _('The ICMP code not in range (-1, 255)') raise ValidationError(msg) cleaned_data['from_port'] = icmp_type cleaned_data['to_port'] = icmp_code elif rule_menu == 'tcp' or rule_menu == 'udp': cleaned_data['ip_protocol'] = rule_menu if port_or_range == "port": cleaned_data["from_port"] = port cleaned_data["to_port"] = port if port is None: msg = _('The specified port is invalid.') raise ValidationError(msg) else: if from_port is None: msg = _('The "from" port number is invalid.') raise ValidationError(msg) if to_port is None: msg = _('The "to" port number is invalid.') raise ValidationError(msg) if to_port < from_port: msg = _('The "to" port number must be greater than ' 'or equal to the "from" port number.') raise ValidationError(msg) elif rule_menu == 'custom': pass else: cleaned_data['ip_protocol'] = self.rules[rule_menu]['ip_protocol'] cleaned_data['from_port'] = int(self.rules[rule_menu]['from_port']) cleaned_data['to_port'] = int(self.rules[rule_menu]['to_port']) cleaned_data['direction'] = self.rules[rule_menu].get('direction') # NOTE(amotoki): There are two cases where cleaned_data['direction'] # is empty: (1) Nova Security Group is used. Since "direction" is # HiddenInput, direction field exists but its value is ''. # (2) Template is used. In this case, the default value is None. # To make sure 'direction' field has 'ingress' or 'egress', # fill this field here if it is not specified. if not cleaned_data['direction']: cleaned_data['direction'] = 'ingress' if remote == "cidr": cleaned_data['security_group'] = None else: cleaned_data['cidr'] = None # If cleaned_data does not contain cidr, cidr is already marked # as invalid, so skip the further validation for cidr. # In addition cleaned_data['cidr'] is None means source_group is used. if 'cidr' in cleaned_data and cleaned_data['cidr'] is not None: cidr = cleaned_data['cidr'] if not cidr: msg = _('CIDR must be specified.') self._errors['cidr'] = self.error_class([msg]) else: # If cidr is specified, ethertype is determined from IP address # version. It is used only when Neutron is enabled. ip_ver = netaddr.IPNetwork(cidr).version cleaned_data['ethertype'] = 'IPv6' if ip_ver == 6 else 'IPv4' return cleaned_data def handle(self, request, data): try: rule = api.network.security_group_rule_create( request, get_int_or_uuid(data['id']), data['direction'], data['ethertype'], data['ip_protocol'], data['from_port'], data['to_port'], data['cidr'], data['security_group']) messages.success(request, _('Successfully added rule: %s') % unicode(rule)) return rule except Exception: redirect = reverse("horizon:project:access_and_security:" "security_groups:detail", args=[data['id']]) exceptions.handle(request, _('Unable to add rule to security group.'), redirect=redirect)
class AddIPSecSiteConnectionAction(workflows.Action): name = forms.CharField(max_length=80, label=_("Name")) description = forms.CharField(initial="", required=False, max_length=80, label=_("Description")) vpnservice_id = forms.ChoiceField( label=_("VPN Service associated with this connection")) ikepolicy_id = forms.ChoiceField( label=_("IKE Policy associated with this connection")) ipsecpolicy_id = forms.ChoiceField( label=_("IPSec Policy associated with this connection")) peer_address = fields.IPField( label=_("Peer gateway public IPv4/IPv6 Address or FQDN"), help_text=_("Peer gateway public IPv4/IPv6 address or FQDN for " "the VPN Connection"), version=fields.IPv4 | fields.IPv6, mask=False) peer_id = fields.IPField( label=_("Peer router identity for authentication (Peer ID)"), help_text=_("Peer router identity for authentication. " "Can be IPv4/IPv6 address, e-mail, key ID, or FQDN"), version=fields.IPv4 | fields.IPv6, mask=False) peer_cidrs = fields.MultiIPField(label=_("Remote peer subnet(s)"), help_text=_( "Remote peer subnet(s) address(es) " "with mask(s) in CIDR format " "separated with commas if needed " "(e.g. 20.1.0.0/24, 21.1.0.0/24)"), version=fields.IPv4 | fields.IPv6, mask=True) psk = forms.CharField(max_length=80, label=_("Pre-Shared Key (PSK) string")) def populate_ikepolicy_id_choices(self, request, context): ikepolicy_id_choices = [('', _("Select IKE Policy"))] try: tenant_id = self.request.user.tenant_id ikepolicies = api.vpn.ikepolicy_list(request, tenant_id=tenant_id) except Exception: exceptions.handle(request, _('Unable to retrieve IKE Policies list.')) ikepolicies = [] for p in ikepolicies: ikepolicy_id_choices.append((p.id, p.name)) self.fields['ikepolicy_id'].choices = ikepolicy_id_choices return ikepolicy_id_choices def populate_ipsecpolicy_id_choices(self, request, context): ipsecpolicy_id_choices = [('', _("Select IPSec Policy"))] try: tenant_id = self.request.user.tenant_id ipsecpolicies = api.vpn.ipsecpolicy_list(request, tenant_id=tenant_id) except Exception: exceptions.handle(request, _('Unable to retrieve IPSec Policies list.')) ipsecpolicies = [] for p in ipsecpolicies: ipsecpolicy_id_choices.append((p.id, p.name)) self.fields['ipsecpolicy_id'].choices = ipsecpolicy_id_choices return ipsecpolicy_id_choices def populate_vpnservice_id_choices(self, request, context): vpnservice_id_choices = [('', _("Select VPN Service"))] try: tenant_id = self.request.user.tenant_id vpnservices = api.vpn.vpnservice_list(request, tenant_id=tenant_id) except Exception: exceptions.handle(request, _('Unable to retrieve VPN Services list.')) vpnservices = [] for s in vpnservices: vpnservice_id_choices.append((s.id, s.name)) self.fields['vpnservice_id'].choices = vpnservice_id_choices return vpnservice_id_choices class Meta: name = _("Add New IPSec Site Connection") permissions = ('openstack.services.network', ) help_text = _("Create IPSec Site Connection for current project.\n\n" "Assign a name and description for the " "IPSec Site Connection. " "All fields in this tab are required.")
class CreateSubnetInfoAction(workflows.Action): with_subnet = forms.BooleanField(label=_("Create Subnet"), initial=True, required=False) subnet_name = forms.CharField(max_length=255, label=_("Subnet Name"), help_text=_("Subnet Name. This field is " "optional."), required=False) cidr = fields.IPField(label=_("Network Address"), required=False, initial="", help_text=_("Network address in CIDR format " "(e.g. 192.168.0.0/24)"), version=fields.IPv4 | fields.IPv6, mask=True) ip_version = forms.ChoiceField(choices=[(4, 'IPv4'), (6, 'IPv6')], label=_("IP Version")) gateway_ip = fields.IPField( label=_("Gateway IP (optional)"), required=False, initial="", help_text=_("IP address of Gateway (e.g. 192.168.0.254) " "The default value is the first IP of the " "network address (e.g. 192.168.0.1 for " "192.168.0.0/24). " "If you use the default, leave blank. " "If you want to use no gateway, " "check 'Disable Gateway' below."), version=fields.IPv4 | fields.IPv6, mask=False) no_gateway = forms.BooleanField(label=_("Disable Gateway"), initial=False, required=False) class Meta: name = _("Subnet") help_text = _('You can create a subnet associated with the new ' 'network, in which case "Network Address" must be ' 'specified. If you wish to create a network WITHOUT a ' 'subnet, uncheck the "Create Subnet" checkbox.') def _check_subnet_data(self, cleaned_data, is_create=True): cidr = cleaned_data.get('cidr') ip_version = int(cleaned_data.get('ip_version')) gateway_ip = cleaned_data.get('gateway_ip') no_gateway = cleaned_data.get('no_gateway') if not cidr: msg = _('Specify "Network Address" or ' 'clear "Create Subnet" checkbox.') raise forms.ValidationError(msg) if cidr: subnet = netaddr.IPNetwork(cidr) if subnet.version != ip_version: msg = _('Network Address and IP version are inconsistent.') raise forms.ValidationError(msg) if (ip_version == 4 and subnet.prefixlen == 32) or \ (ip_version == 6 and subnet.prefixlen == 128): msg = _( "The subnet in the Network Address is too small (/%s)." % subnet.prefixlen) raise forms.ValidationError(msg) if not no_gateway and gateway_ip: if netaddr.IPAddress(gateway_ip).version is not ip_version: msg = _('Gateway IP and IP version are inconsistent.') raise forms.ValidationError(msg) if not is_create and not no_gateway and not gateway_ip: msg = _('Specify IP address of gateway or ' 'check "Disable Gateway".') raise forms.ValidationError(msg) def clean(self): cleaned_data = super(CreateSubnetInfoAction, self).clean() with_subnet = cleaned_data.get('with_subnet') if not with_subnet: return cleaned_data self._check_subnet_data(cleaned_data) return cleaned_data
class AddRule(forms.SelfHandlingForm): ip_protocol = forms.ChoiceField( label=_('IP Protocol'), choices=[('tcp', 'TCP'), ('udp', 'UDP'), ('icmp', 'ICMP')], help_text=_("The protocol which this " "rule should be applied to."), widget=forms.Select(attrs={'class': 'switchable'})) from_port = forms.IntegerField( label=_("From Port"), help_text=_("TCP/UDP: Enter integer value " "between 1 and 65535. ICMP: " "enter a value for ICMP type " "in the range (-1: 255)"), widget=forms.TextInput(attrs={ 'data': _('From Port'), 'data-icmp': _('Type') }), validators=[validate_port_range]) to_port = forms.IntegerField(label=_("To Port"), help_text=_("TCP/UDP: Enter integer value " "between 1 and 65535. ICMP: " "enter a value for ICMP code " "in the range (-1: 255)"), widget=forms.TextInput(attrs={ 'data': _('To Port'), 'data-icmp': _('Code') }), validators=[validate_port_range]) source_group = forms.ChoiceField(label=_('Source Group'), required=False, help_text=_("To specify an allowed IP " "range, select CIDR. To " "allow access from all " "members of another security " "group select Source Group.")) cidr = fields.IPField(label=_("CIDR"), required=False, initial="0.0.0.0/0", help_text=_("Classless Inter-Domain Routing " "(e.g. 192.168.0.0/24)"), version=fields.IPv4 | fields.IPv6, mask=True) security_group_id = forms.IntegerField(widget=forms.HiddenInput()) def __init__(self, *args, **kwargs): sg_list = kwargs.pop('sg_list', []) super(AddRule, self).__init__(*args, **kwargs) # Determine if there are security groups available for the # source group option; add the choices and enable the option if so. security_groups_choices = [("", "CIDR")] if sg_list: security_groups_choices.append(('Security Group', sg_list)) self.fields['source_group'].choices = security_groups_choices def clean(self): cleaned_data = super(AddRule, self).clean() from_port = cleaned_data.get("from_port", None) to_port = cleaned_data.get("to_port", None) cidr = cleaned_data.get("cidr", None) ip_proto = cleaned_data.get('ip_protocol', None) source_group = cleaned_data.get("source_group", None) if ip_proto == 'icmp': if from_port is None: msg = _('The ICMP type is invalid.') raise ValidationError(msg) if to_port is None: msg = _('The ICMP code is invalid.') raise ValidationError(msg) if from_port not in xrange(-1, 256): msg = _('The ICMP type not in range (-1, 255)') raise ValidationError(msg) if to_port not in xrange(-1, 256): msg = _('The ICMP code not in range (-1, 255)') raise ValidationError(msg) else: if from_port is None: msg = _('The "from" port number is invalid.') raise ValidationError(msg) if to_port is None: msg = _('The "to" port number is invalid.') raise ValidationError(msg) if to_port < from_port: msg = _('The "to" port number must be greater than ' 'or equal to the "from" port number.') raise ValidationError(msg) if source_group and cidr != self.fields['cidr'].initial: # Specifying a source group *and* a custom CIDR is invalid. msg = _('Either CIDR or Source Group may be specified, ' 'but not both.') raise ValidationError(msg) elif source_group: # If a source group is specified, clear the CIDR from its default cleaned_data['cidr'] = None else: # If only cidr is specified, clear the source_group entirely cleaned_data['source_group'] = None return cleaned_data def handle(self, request, data): try: rule = api.security_group_rule_create( request, data['security_group_id'], data['ip_protocol'], data['from_port'], data['to_port'], data['cidr'], data['source_group']) messages.success(request, _('Successfully added rule: %s') % unicode(rule)) return rule except: redirect = reverse("horizon:project:access_and_security:index") exceptions.handle(request, _('Unable to add rule to security group.'), redirect=redirect)
class CreateSiteInfoAction(workflows.Action): with_site = forms.BooleanField( label=_("Add your Enterprise Site (below) to this VPN"), initial=True, required=False) CHOICES = (('Data_Center_San_Jose_B', 'Enterprise Data Center in San Jose B'), ('Data_Center_Jorvas', 'Enterprise Data Center in Jorvas')) sitechoice = forms.ChoiceField(required=False, label='Existent Enterprise Site', choices=CHOICES) site_name = forms.CharField( max_length=255, label= _("If your Enterprise Site (running the VPN agent with chosen VPN type) does not appear, add its config:" ), help_text=_("Enterprise Site Name. This field is " "optional."), required=False) remote_keystone_endpoint = fields.IPField( label=_("Enterprise Keystone v2 IP address (Port 5000)"), required=False, initial="10.126.71.249", help_text=_( "Enterprise Keystone Network address in IPv4 or IPv6 address format " "(e.g. 192.168.0.0)"), version=fields.IPv4 | fields.IPv6, mask=False) # ip_version = forms.ChoiceField(choices=[(4, 'IPv4'), (6, 'IPv6')], # label=_("Keystone server IP Version")) remote_login = forms.CharField( max_length=255, label=_("User LOGIN in Enterprise site"), help_text=_( "Tenant's user LOGIN in Enterprise site. In case you do not want to provide a 24hours expiration token from your Enterprise Keystone " "each time you connect your VPN. This field is " "optional."), required=False) remote_tenant = forms.CharField( label=_("Tenant NAME in Enterprise"), help_text=_("Tenant's NAME in Enterprise site. This field is " "optional."), required=False) # widget=forms.PasswordInput(render_value=False), required=False) add_local_site = forms.BooleanField( label=_("Add this Provider Site to this VPN"), help_text=_( "Other Sites for this Provider are in other Availability Zones"), initial=True, required=False) class Meta: name = ("Provider and Enterprise Sites") help_text = _( 'You can add a Provider Site as well as your Enterprise Site associated with the new ' 'VPN, in which case "Enterprise Keystone IP address and user credentials" must be ' 'specified. If you wish to create a vpn WITHOUT adding sites, ' ' uncheck the "Add Site" top and bottom checkboxes.') def _check_site_data(self, cleaned_data, is_create=True): rke = cleaned_data.get('remote_keystone_endpoint') ws = cleaned_data.get('with_site') #ip_version = int(cleaned_data.get('ip_version')) als = cleaned_data.get('add_local_site') sn = cleaned_data.get('site_name') rl = cleaned_data.get('remote_login') rp = cleaned_data.get('remote_tenant') if not rke: msg = _('Specify "Enterprise Keystone IP Address" or ' 'clear "Add your Enterprise Site to this VPN" checkbox.') raise forms.ValidationError(msg) if rke: site = netaddr.IPNetwork(rke) # if site.version != ip_version: # msg = _('Keystone IP Address and IP version are inconsistent.') # raise forms.ValidationError(msg) if not als and ws: msg = _( 'Make sure you added a Provider Site for the Enterprise Site ' 'Check "Add this local Provider Site to this VPN in the bottom".' ) raise forms.ValidationError(msg) if sn and not rke: msg = _( 'Make sure you added a keystone endpoint for you newly added site' ) raise forms.ValidationError(msg) if rl and not rp: msg = _( 'Make sure you added a password for the login your provided (we do not store it)' ) raise forms.ValidationError(msg) def clean(self): cleaned_data = super(CreateSiteInfoAction, self).clean() with_site = cleaned_data.get('with_site') if not with_site: return cleaned_data self._check_site_data(cleaned_data) return cleaned_data
class AddInterface(forms.SelfHandlingForm): subnet_id = forms.ChoiceField(label=_("Subnet")) ip_address = fields.IPField( label=_("IP Address (optional)"), required=False, initial="", help_text=_("You can specify an IP address of the interface " "created if you want (e.g. 192.168.0.254)."), version=fields.IPv4 | fields.IPv6, mask=False) router_name = forms.CharField( label=_("Router Name"), widget=forms.TextInput(attrs={'readonly': 'readonly'})) router_id = forms.CharField( label=_("Router ID"), widget=forms.TextInput(attrs={'readonly': 'readonly'})) failure_url = 'horizon:project:routers:detail' def __init__(self, request, *args, **kwargs): super(AddInterface, self).__init__(request, *args, **kwargs) c = self.populate_subnet_id_choices(request) self.fields['subnet_id'].choices = c def populate_subnet_id_choices(self, request): tenant_id = self.request.user.tenant_id networks = [] try: networks = api.neutron.network_list_for_tenant(request, tenant_id) except Exception as e: msg = _('Failed to get network list %s') % e.message LOG.info(msg) messages.error(request, msg) redirect = reverse(self.failure_url, args=[request.REQUEST['router_id']]) exceptions.handle(request, msg, redirect=redirect) return choices = [] for n in networks: net_name = n.name + ': ' if n.name else '' choices += [(subnet.id, '%s%s (%s)' % (net_name, subnet.cidr, subnet.name or subnet.id)) for subnet in n['subnets']] if choices: choices.insert(0, ("", _("Select Subnet"))) else: choices.insert(0, ("", _("No subnets available."))) return choices def handle(self, request, data): if data['ip_address']: port = self._add_interface_by_port(request, data) else: port = self._add_interface_by_subnet(request, data) msg = _('Interface added') if port: msg += ' ' + port.fixed_ips[0]['ip_address'] LOG.debug(msg) messages.success(request, msg) return True def _add_interface_by_subnet(self, request, data): router_id = data['router_id'] try: router_inf = api.neutron.router_add_interface( request, router_id, subnet_id=data['subnet_id']) except Exception as e: self._handle_error(request, router_id, e) try: port = api.neutron.port_get(request, router_inf['port_id']) except Exception: # Ignore an error when port_get() since it is just # to get an IP address for the interface. port = None return port def _add_interface_by_port(self, request, data): router_id = data['router_id'] subnet_id = data['subnet_id'] try: subnet = api.neutron.subnet_get(request, subnet_id) except Exception: msg = _('Unable to get subnet "%s"') % subnet_id self._handle_error(request, router_id, msg) try: ip_address = data['ip_address'] body = { 'network_id': subnet.network_id, 'fixed_ips': [{ 'subnet_id': subnet.id, 'ip_address': ip_address }] } port = api.neutron.port_create(request, **body) except Exception as e: self._handle_error(request, router_id, e) try: api.neutron.router_add_interface(request, router_id, port_id=port.id) except Exception as e: self._delete_port(request, port) self._handle_error(request, router_id, e) return port def _handle_error(self, request, router_id, reason): msg = _('Failed to add_interface: %s') % reason LOG.info(msg) redirect = reverse(self.failure_url, args=[router_id]) exceptions.handle(request, msg, redirect=redirect) def _delete_port(self, request, port): try: api.neutron.port_delete(request, port.id) except Exception: msg = _('Failed to delete port %s') % port.id LOG.info(msg) exceptions.handle(request, msg)
class AddRule(forms.SelfHandlingForm): id = forms.CharField(widget=forms.HiddenInput()) ip_protocol = forms.ChoiceField(label=_('Rule'), widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'protocol'})) port_or_range = forms.ChoiceField(label=_('Open'), choices=[('port', _('Port')), ('range', _('Port Range'))], widget=forms.Select(attrs={ 'class': 'switchable switched', 'data-slug': 'range', 'data-switch-on': 'protocol', 'data-protocol-tcp': _('Open'), 'data-protocol-udp': _('Open')})) port = forms.IntegerField(label=_("Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'range', 'data-range-port': _('Port')}), validators=[validate_port_range]) from_port = forms.IntegerField(label=_("From Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'range', 'data-range-range': _('From Port')}), validators=[validate_port_range]) to_port = forms.IntegerField(label=_("To Port"), required=False, help_text=_("Enter an integer value " "between 1 and 65535."), widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'range', 'data-range-range': _('To Port')}), validators=[validate_port_range]) icmp_type = forms.IntegerField(label=_("Type"), required=False, help_text=_("Enter a value for ICMP type " "in the range (-1: 255)"), widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'protocol', 'data-protocol-icmp': _('Type')}), validators=[validate_port_range]) icmp_code = forms.IntegerField(label=_("Code"), required=False, help_text=_("Enter a value for ICMP code " "in the range (-1: 255)"), widget=forms.TextInput(attrs={ 'class': 'switched', 'data-switch-on': 'protocol', 'data-protocol-icmp': _('Code')}), validators=[validate_port_range]) source = forms.ChoiceField(label=_('Source'), choices=[('cidr', _('CIDR')), ('sg', _('Security Group'))], help_text=_('To specify an allowed IP ' 'range, select "CIDR". To ' 'allow access from all ' 'members of another security ' 'group select "Security ' 'Group".'), widget=forms.Select(attrs={ 'class': 'switchable', 'data-slug': 'source'})) cidr = fields.IPField(label=_("CIDR"), required=False, initial="0.0.0.0/0", help_text=_("Classless Inter-Domain Routing " "(e.g. 192.168.0.0/24)"), version=fields.IPv4 | fields.IPv6, mask=True, widget=forms.TextInput( attrs={'class': 'switched', 'data-switch-on': 'source', 'data-source-cidr': _('CIDR')})) security_group = forms.ChoiceField(label=_('Security Group'), required=False, widget=forms.Select(attrs={ 'class': 'switched', 'data-switch-on': 'source', 'data-source-sg': _('Security ' 'Group')})) def __init__(self, *args, **kwargs): sg_list = kwargs.pop('sg_list', []) super(AddRule, self).__init__(*args, **kwargs) # Determine if there are security groups available for the # source group option; add the choices and enable the option if so. if sg_list: security_groups_choices = sg_list else: security_groups_choices = [("", _("No security groups available"))] self.fields['security_group'].choices = security_groups_choices rules_dict = getattr(settings, 'SECURITY_GROUP_RULES', {}) common_rules = [(k, _(rules_dict[k]['name'])) for k in rules_dict] common_rules.sort() custom_rules = [('tcp', _('Custom TCP Rule')), ('udp', _('Custom UDP Rule')), ('icmp', _('Custom ICMP Rule'))] self.fields['ip_protocol'].choices = custom_rules + common_rules self.rules = rules_dict def clean(self): cleaned_data = super(AddRule, self).clean() ip_proto = cleaned_data.get('ip_protocol') port_or_range = cleaned_data.get("port_or_range") source = cleaned_data.get("source") icmp_type = cleaned_data.get("icmp_type", None) icmp_code = cleaned_data.get("icmp_code", None) from_port = cleaned_data.get("from_port", None) to_port = cleaned_data.get("to_port", None) port = cleaned_data.get("port", None) if ip_proto == 'icmp': if icmp_type is None: msg = _('The ICMP type is invalid.') raise ValidationError(msg) if icmp_code is None: msg = _('The ICMP code is invalid.') raise ValidationError(msg) if icmp_type not in xrange(-1, 256): msg = _('The ICMP type not in range (-1, 255)') raise ValidationError(msg) if icmp_code not in xrange(-1, 256): msg = _('The ICMP code not in range (-1, 255)') raise ValidationError(msg) cleaned_data['from_port'] = icmp_type cleaned_data['to_port'] = icmp_code elif ip_proto == 'tcp' or ip_proto == 'udp': if port_or_range == "port": cleaned_data["from_port"] = port cleaned_data["to_port"] = port if port is None: msg = _('The specified port is invalid.') raise ValidationError(msg) else: if from_port is None: msg = _('The "from" port number is invalid.') raise ValidationError(msg) if to_port is None: msg = _('The "to" port number is invalid.') raise ValidationError(msg) if to_port < from_port: msg = _('The "to" port number must be greater than ' 'or equal to the "from" port number.') raise ValidationError(msg) else: cleaned_data['ip_protocol'] = self.rules[ip_proto]['ip_protocol'] cleaned_data['from_port'] = int(self.rules[ip_proto]['from_port']) cleaned_data['to_port'] = int(self.rules[ip_proto]['to_port']) if source == "cidr": cleaned_data['security_group'] = None else: cleaned_data['cidr'] = None return cleaned_data def handle(self, request, data): try: rule = api.nova.security_group_rule_create( request, get_int_or_uuid(data['id']), data['ip_protocol'], data['from_port'], data['to_port'], data['cidr'], data['security_group']) messages.success(request, _('Successfully added rule: %s') % unicode(rule)) return rule except: redirect = reverse("horizon:project:access_and_security:" "security_groups:detail", args=[data['id']]) exceptions.handle(request, _('Unable to add rule to security group.'), redirect=redirect)
class AddVipAction(workflows.Action): name = forms.CharField(max_length=80, label=_("Name")) description = forms.CharField(initial="", required=False, max_length=80, label=_("Description")) floatip_address = forms.ChoiceField( label=_("VIP Address from Floating IPs"), widget=forms.Select(attrs={'disabled': 'disabled'}), required=False) other_address = fields.IPField(required=False, initial="", version=fields.IPv4, mask=False) protocol_port = forms.IntegerField(label=_("Protocol Port"), min_value=1, help_text=_("Enter an integer value " "between 1 and 65535."), validators=[validate_port_range]) protocol = forms.ChoiceField(label=_("Protocol")) session_persistence = forms.ChoiceField(required=False, initial={}, label=_("Session Persistence")) cookie_name = forms.CharField(initial="", required=False, max_length=80, label=_("Cookie Name"), help_text=_( "Required for APP_COOKIE persistence;" " Ignored otherwise.")) connection_limit = forms.IntegerField( min_value=-1, label=_("Connection Limit"), help_text=_("Maximum number of connections allowed " "for the VIP or '-1' if the limit is not set")) admin_state_up = forms.BooleanField(label=_("Admin State"), initial=True, required=False) def __init__(self, request, *args, **kwargs): super(AddVipAction, self).__init__(request, *args, **kwargs) self.fields['other_address'].label = _("Specify a free IP address" " from %s" % args[0]['subnet']) protocol_choices = [('', _("Select a Protocol"))] protocol_choices.append(('HTTP', 'HTTP')) protocol_choices.append(('HTTPS', 'HTTPS')) self.fields['protocol'].choices = protocol_choices session_persistence_choices = [('', _("Set Session Persistence"))] for mode in ('SOURCE_IP', 'HTTP_COOKIE', 'APP_COOKIE'): session_persistence_choices.append((mode, mode)) self.fields[ 'session_persistence'].choices = session_persistence_choices floatip_address_choices = [('', _("Currently Not Supported"))] self.fields['floatip_address'].choices = floatip_address_choices def clean(self): cleaned_data = super(AddVipAction, self).clean() if (cleaned_data.get('session_persistence') == 'APP_COOKIE' and not cleaned_data.get('cookie_name')): msg = _('Cookie name is required for APP_COOKIE persistence.') self._errors['cookie_name'] = self.error_class([msg]) return cleaned_data class Meta: name = _("AddVip") permissions = ('openstack.services.network', ) help_text = _("Create a VIP for this pool. " "Assign a name and description for the VIP. " "Specify an IP address and port for the VIP. " "Choose the protocol and session persistence " "method for the VIP." "Specify the max connections allowed. " "Admin State is UP (checked) by default.")
class UpdateRule(forms.SelfHandlingForm): name = forms.CharField(max_length=80, label=_("Name"), required=False) description = forms.CharField(required=False, max_length=80, label=_("Description")) protocol = forms.ChoiceField(label=_("Protocol"), required=False, help_text=_('Protocol for the firewall rule')) action = forms.ChoiceField(label=_("Action"), required=False, help_text=_('Action for the firewall rule')) source_ip_address = fields.IPField( label=_("Source IP Address/Subnet"), version=fields.IPv4 | fields.IPv6, required=False, mask=True, help_text=_('Source IP address or subnet')) destination_ip_address = fields.IPField( label=_('Destination IP Address/Subnet'), version=fields.IPv4 | fields.IPv6, required=False, mask=True, help_text=_('Destination IP address or subnet')) source_port = forms.CharField( max_length=80, label=_("Source Port/Port Range"), required=False, validators=[port_validator], help_text=_('Source port (integer in [1, 65535] or range in a:b)')) destination_port = forms.CharField( max_length=80, label=_("Destination Port/Port Range"), required=False, validators=[port_validator], help_text=_('Destination port (integer in [1, 65535] or range' ' in a:b)')) shared = forms.BooleanField(label=_("Shared"), required=False) enabled = forms.BooleanField(label=_("Enabled"), required=False) failure_url = 'horizon:project:firewalls:index' def __init__(self, request, *args, **kwargs): super(UpdateRule, self).__init__(request, *args, **kwargs) protocol = kwargs['initial']['protocol'].upper() action = kwargs['initial']['action'].upper() protocol_choices = [(protocol, protocol)] for tup in [('TCP', _('TCP')), ('UDP', _('UDP')), ('ICMP', _('ICMP'))]: if tup[0] != protocol: protocol_choices.append(tup) self.fields['protocol'].choices = protocol_choices action_choices = [(action, action)] for tup in [('ALLOW', _('ALLOW')), ('DENY', _('DENY'))]: if tup[0] != action: action_choices.append(tup) self.fields['action'].choices = action_choices def handle(self, request, context): rule_id = self.initial['rule_id'] name_or_id = context.get('name') or rule_id for f in [ 'source_ip_address', 'destination_ip_address', 'source_port', 'destination_port' ]: if not context[f]: context[f] = None try: rule = api.fwaas.rule_update(request, rule_id, **context) msg = _('Rule %s was successfully updated.') % name_or_id LOG.debug(msg) messages.success(request, msg) return rule except Exception as e: msg = _('Failed to update rule %(name)s: %(reason)s' % { 'name': name_or_id, 'reason': e }) LOG.error(msg) redirect = reverse(self.failure_url) exceptions.handle(request, msg, redirect=redirect)
class AddIPSecSiteConnectionAction(workflows.Action): name = forms.CharField(max_length=80, label=_("Name")) description = forms.CharField( initial="", required=False, max_length=80, label=_("Description")) vpnservice_id = forms.ChoiceField( label=_("VPN Service associated with this connection")) ikepolicy_id = forms.ChoiceField( label=_("IKE Policy associated with this connection")) ipsecpolicy_id = forms.ChoiceField( label=_("IPSec Policy associated with this connection")) peer_address = fields.IPField(label=_("Remote Peer IP Address"), help_text=_("Remote peer IP address for " "the VPN Connection " "(e.g. 172.0.0.2)"), version=fields.IPv4 | fields.IPv6, mask=False) peer_id = fields.IPField( label=_("Remote branch router identity (Peer ID)"), help_text=_("IP address of remote branch router (e.g. 172.0.0.2)"), version=fields.IPv4 | fields.IPv6, mask=False) peer_cidrs = fields.IPField(label=_("Remote peer subnet"), help_text=_("Remote peer subnet address " "with mask in CIDR format " "(e.g. 20.1.0.0/24)"), version=fields.IPv4 | fields.IPv6, mask=True) psk = forms.CharField(max_length=80, label=_("Pre-Shared Key (PSK) string")) def populate_ikepolicy_id_choices(self, request, context): ikepolicy_id_choices = [('', _("Select IKE Policy"))] try: ikepolicies = api.vpn.ikepolicies_get(request) except Exception: exceptions.handle(request, _('Unable to retrieve IKE Policies list.')) ikepolicies = [] for p in ikepolicies: ikepolicy_id_choices.append((p.id, p.name)) self.fields['ikepolicy_id'].choices = ikepolicy_id_choices return ikepolicy_id_choices def populate_ipsecpolicy_id_choices(self, request, context): ipsecpolicy_id_choices = [('', _("Select IPSec Policy"))] try: ipsecpolicies = api.vpn.ipsecpolicies_get(request) except Exception: exceptions.handle(request, _('Unable to retrieve IPSec Policies list.')) ipsecpolicies = [] for p in ipsecpolicies: ipsecpolicy_id_choices.append((p.id, p.name)) self.fields['ipsecpolicy_id'].choices = ipsecpolicy_id_choices return ipsecpolicy_id_choices def populate_vpnservice_id_choices(self, request, context): vpnservice_id_choices = [('', _("Select VPN Service"))] try: vpnservices = api.vpn.vpnservices_get(request) except Exception: exceptions.handle(request, _('Unable to retrieve VPN Services list.')) vpnservices = [] for s in vpnservices: vpnservice_id_choices.append((s.id, s.name)) self.fields['vpnservice_id'].choices = vpnservice_id_choices return vpnservice_id_choices class Meta: name = _("Add New IPSec Site Connection") permissions = ('openstack.services.network',) help_text = _("Create IPSec Site Connection for current project.\n\n" "Assign a name and description for the " "IPSec Site Connection. " "All fields in this tab are required." )
class AddRule(forms.SelfHandlingForm): ip_protocol = forms.ChoiceField( label=_('IP Protocol'), choices=[('tcp', 'TCP'), ('udp', 'UDP'), ('icmp', 'ICMP')], widget=forms.Select(attrs={'class': 'switchable'})) from_port = forms.IntegerField( label=_("From Port"), help_text=_("TCP/UDP: Enter integer value " "between 1 and 65535. ICMP: " "enter a value for ICMP type " "in the range (-1: 255)"), widget=forms.TextInput(attrs={ 'data': _('From Port'), 'data-icmp': _('Type') }), validators=[validate_port_range]) to_port = forms.IntegerField(label=_("To Port"), help_text=_("TCP/UDP: Enter integer value " "between 1 and 65535. ICMP: " "enter a value for ICMP code " "in the range (-1: 255)"), widget=forms.TextInput(attrs={ 'data': _('To Port'), 'data-icmp': _('Code') }), validators=[validate_port_range]) source_group = forms.ChoiceField(label=_('Source Group'), required=False) cidr = fields.IPField(label=_("CIDR"), required=False, initial="0.0.0.0/0", help_text=_("Classless Inter-Domain Routing " "(e.g. 192.168.0.0/24)"), version=fields.IPv4 | fields.IPv6, mask=True) security_group_id = forms.IntegerField(widget=forms.HiddenInput()) def __init__(self, *args, **kwargs): super(AddRule, self).__init__(*args, **kwargs) initials = kwargs.get("initial", {}) current_group_id = initials.get('security_group_id', 0) security_groups = initials.get('security_group_list', []) security_groups_choices = [("", "CIDR")] # default choice is CIDR group_choices = [ s for s in security_groups if str(s[0]) != current_group_id ] if len(group_choices): # add group choice if available security_groups_choices.append(('Security Group', group_choices)) self.fields['source_group'].choices = security_groups_choices def clean(self): cleaned_data = super(AddRule, self).clean() from_port = cleaned_data.get("from_port", None) to_port = cleaned_data.get("to_port", None) cidr = cleaned_data.get("cidr", None) ip_proto = cleaned_data.get('ip_protocol', None) source_group = cleaned_data.get("source_group", None) if ip_proto == 'icmp': if from_port == None: msg = _('The ICMP type is invalid.') raise ValidationError(msg) if to_port == None: msg = _('The ICMP code is invalid.') raise ValidationError(msg) if from_port not in xrange(-1, 256): msg = _('The ICMP type not in range (-1, 255)') raise ValidationError(msg) if to_port not in xrange(-1, 256): msg = _('The ICMP code not in range (-1, 255)') raise ValidationError(msg) else: if from_port == None: msg = _('The "from" port number is invalid.') raise ValidationError(msg) if to_port == None: msg = _('The "to" port number is invalid.') raise ValidationError(msg) if to_port < from_port: msg = _('The "to" port number must be greater than ' 'or equal to the "from" port number.') raise ValidationError(msg) if source_group and cidr != self.fields['cidr'].initial: # Specifying a source group *and* a custom CIDR is invalid. msg = _('Either CIDR or Source Group may be specified, ' 'but not both.') raise ValidationError(msg) elif source_group: # If a source group is specified, clear the CIDR from its default cleaned_data['cidr'] = None else: # If only cidr is specified, clear the source_group entirely cleaned_data['source_group'] = None return cleaned_data def handle(self, request, data): try: rule = api.security_group_rule_create( request, data['security_group_id'], data['ip_protocol'], data['from_port'], data['to_port'], data['cidr'], data['source_group']) messages.success(request, _('Successfully added rule: %s') \ % unicode(rule)) except: exceptions.handle(request, _('Unable to add rule to security group.')) return shortcuts.redirect("horizon:nova:access_and_security:index")