Allow to convert IPV4 addresse from text to binary
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
oslo.utils |
Fix Released
|
Undecided
|
Unassigned |
Bug Description
Heat Common constraints accept an arbitrary string of 1 to 10 numbers as a valid IP.
Using the custom_constraint ip_addr in a template does not work as expect.
Using something like
- notanipadress
- 1024.1024.10.24
Produce a parameter error like expected
~~~
(overcloud) [stack@undercloud-0 Parameter]$ openstack stack create -t Parameterconstr
ERROR: Parameter 'ip_address' is invalid: Error validating value 'notanipadress': Invalid IP address
(overcloud) [stack@undercloud-0 Parameter]$ openstack stack create -t Parameterconstr
ERROR: Parameter 'ip_address' is invalid: Error validating value '1024.1024.10.24': Invalid IP address
~~~
But using arbitrary strings of numbers less then 11 numbers does not
~~~
(overcloud) [stack@undercloud-0 Parameter]$ openstack stack create -t Parameterconstr
+------
| Field | Value |
+------
| id | 8cca736a-
| stack_name | teststack10 |
| description | Simple demonstration on what happens when use a function that is from a template version which higher then the version specified in the template |
| creation_time | 2021-02-
| updated_time | None |
| stack_status | CREATE_COMPLETE |
| stack_status_reason | Stack CREATE completed successfully |
+------
(overcloud) [stack@undercloud-0 Parameter]$ openstack stack create -t Parameterconstr
+------
| Field | Value |
+------
| id | f6739aad-
| stack_name | teststack11 |
| description | Simple demonstration on what happens when use a function that is from a template version which higher then the version specified in the template |
| creation_time | 2021-02-
| updated_time | None |
| stack_status | CREATE_COMPLETE |
| stack_status_reason | Stack CREATE completed successfully |
+------
(overcloud) [stack@undercloud-0 Parameter]$ openstack stack create -t Parameterconstr
ERROR: Parameter 'ip_address' is invalid: Error validating value '11111111111111
(overcloud) [stack@undercloud-0 Parameter]$ openstack stack create -t Parameterconstr
ERROR: Parameter 'ip_address' is invalid: Error validating value '0101010101010': Invalid IP address
(overcloud) [stack@undercloud-0 Parameter]$ openstack stack create -t Parameterconstr
+------
| Field | Value |
+------
| id | 3b60f530-
| stack_name | teststack13 |
| description | Simple demonstration on what happens when use a function that is from a template version which higher then the version specified in the template |
| creation_time | 2021-02-
| updated_time | None |
| stack_status | CREATE_COMPLETE |
| stack_status_reason | Stack CREATE completed successfully |
~~~
Version-Release number of selected component (if applicable):
- python2-
- openstack-
- python2-
How reproducible:
Every time
Steps to Reproduce:
1. use the a template like the following
openstack stack create -t Parameterconstr
~~~
heat_template_
description: Simple demonstration of heat parameter constraints
parameters:
demo:
type: string
label: demo
description: just a useless var
demopassword:
type: string
label: demo password
description: just a useless var
default: demopassword
constraints:
- length: { min: 8, max: 24 }
- allowed_pattern: "[a-zA-Z0-9]*"
ip_address:
type: string
label: IP ip_address
constraints:
- custom_constraint: ip_addr
resources:
cloud_config:
type: OS::Heat:
properties:
cloud_config:
users:
- name: {get_param: demo}
passwd: { digest: ['sha512', {get_param: demopassword}]}
~~~
Actual results:
~~~
(overcloud) [stack@undercloud-0 Parameter]$ openstack stack create -t Parameterconstr
+------
| Field | Value |
+------
| id | 3b60f530-
| stack_name | teststack13 |
| description | Simple demonstration on what happens when use a function that is from a template version which higher then the version specified in the template |
| creation_time | 2021-02-
| updated_time | None |
| stack_status | CREATE_COMPLETE |
| stack_status_reason | Stack CREATE completed successfully
~~~
Expected results:
~~~
(overcloud) [stack@undercloud-0 Parameter]$ openstack stack create -t Parameterconstr
ERROR: Parameter 'ip_address' is invalid: Error validating value '010101010101': Invalid IP address
~~~
Additional info:
/usr/lib/
~~~
from oslo_utils import netutils
from oslo_utils import timeutils
from heat.common.i18n import _
from heat.common import netutils as heat_netutils
from heat.engine import constraints
class TestConstraintD
def validate_
class IPConstraint(
def validate(self, value, context, template=None):
return netutils.
~~~
/usr/lib/
~~~
def is_valid_
"""Verify that address represents a valid IPv4 address.
:param address: Value to verify
:type address: string
:returns: bool
.. versionadded:: 1.1
"""
try:
return netaddr.
except netaddr.
return False
def is_valid_
"""Verify that address represents a valid IPv6 address.
:param address: Value to verify
:type address: string
:returns: bool
.. versionadded:: 1.1
"""
if not address:
return False
parts = address.rsplit("%", 1)
address = parts[0]
scope = parts[1] if len(parts) > 1 else None
if scope is not None and (len(scope) < 1 or len(scope) > 15):
return False
try:
return netaddr.
except netaddr.
return False
...................
def is_valid_
"""Verify that address represents a valid IP address.
:param address: Value to verify
:type address: string
:returns: bool
.. versionadded:: 1.1
"""
return is_valid_
~~~~
At first glance this behave come from `netaddr` and not from `oslo.utils`:
```
$ tox -e venv -- python
>>> from oslo_utils import netutils
>>> netutils.
False
>>> netutils.
True
>>> import netaddr
>>> netaddr.
False
>>> netaddr.
True
```
Oslo.utils just wrap the `netaddr`[1] module and return its outcome [2].
This is behavior is something expected.
This is not an invalid input.
By default, valid_ipv4() uses the inet_aton() C function to verify input which follows the following input formatting rules:
a.b.c.d Each of the four numeric parts specifies a byte of the address; the bytes are assigned in left-to-right order to produce the binary address.
a.b.c Parts a and b specify the first two bytes of the binary address. Part c is interpreted as a 16-bit value that defines the rightmost two bytes of the binary address. This notation is suitable for specifying (outmoded) Class B network addresses.
a.b Part a specifies the first byte of the binary address. Part b is interpreted as a 24-bit value that defines the rightmost three bytes of the binary address. This notation is suitable for specifying (outmoded) Class A network addresses.
a The value is interpreted as a 32-bit value that is stored directly into the binary address without any byte rearrangement.
ref: http://
Therefore, '10' falls under the 4th option (a) where the number is treated as a 32-bit value. Written in dotted decimal format it would be '0.0.0.10' or in hex \x00\x00\x00\x0A Python3 shows it as a byte array b'\x00 \x00\x00\n' (\n newline being the ASCII character 10)
To validate the dotted decimal notation pass the INET_PTON flag to have the function use inet_pton() instead of inet_aton() which evaluates ipv4 and ipv6 addresses using proper formatting requirements:
```
>>> import netaddr
>>> netaddr.
True
>>> netaddr.
False
```
However oslo.utils doesn't accept `flags` so it could be an improvement if you decide to use `INET_PTON` rather than `INET_ATON` that's the default:
https:/
For further details please take a look too:
Changed in oslo.utils: | |
status: | New → Fix Released |
This issue was fixed in the openstack/ oslo.utils 4.8.0 release.