35fe0e3b0d
This specification describes how to support address groups in security group rules. Change-Id: Ib58afde9ed58092ffbc94f7d522d5f5d034b832b Related-Bug: #1592028
709 lines
23 KiB
ReStructuredText
709 lines
23 KiB
ReStructuredText
..
|
|
This work is licensed under a Creative Commons Attribution 3.0 Unported
|
|
License.
|
|
|
|
http://creativecommons.org/licenses/by/3.0/legalcode
|
|
|
|
==============================================
|
|
Address Groups Support in Security Group Rules
|
|
==============================================
|
|
|
|
https://bugs.launchpad.net/neutron/+bug/1592028
|
|
|
|
This specification describes how to support address groups (groups of IP
|
|
address blocks) in Neutron security group rules. The concept of address groups
|
|
was introduced in FWaaS v2.0 but not implemented [1].
|
|
|
|
Problem Description
|
|
===================
|
|
|
|
Neutron security group rules currently support using an IP address block or a
|
|
security group as the remote end of the network access rule. In actual usage,
|
|
an OpenStack cloud may require connectivity between instances and external
|
|
services which are not provisioned by OpenStack. And each service may also
|
|
have multiple endpoint addresses which are not contiguous. To allow the
|
|
connectivity, one rule per external address needs to be created which can be
|
|
very cumbersome and difficult to maintain as the number of external addresses
|
|
may be substantial.
|
|
|
|
|
|
Proposed Change
|
|
===============
|
|
|
|
Add an API to aggregate IP address blocks into an address group object which
|
|
could be later referenced when creating a security group rule. Thus the number
|
|
of security group rules can be effectively reduced when there is the need to
|
|
allow connectivity to a number of external service addresses. When IP addresses
|
|
are updated in the address group, changes will also be reflected in the
|
|
associated security group rules.
|
|
|
|
|
|
REST API Impact
|
|
---------------
|
|
|
|
New address groups API
|
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
+-------------------+---------+-------+------+---------------------------------------+
|
|
| Attribute | Type | Req | CRUD | Description |
|
|
+===================+=========+=======+======+=======================================+
|
|
| id | uuid-str| N/A | R | Unique identifier for the |
|
|
| | | | | address_group object. |
|
|
+-------------------+---------+-------+------+---------------------------------------+
|
|
| name | String | No | CRU | Human readable name for the address |
|
|
| | | | | group (255 characters limit). Does not|
|
|
| | | | | have to be unique. |
|
|
+-------------------+---------+-------+------+---------------------------------------+
|
|
| description | String | No | CRU | Human readable description for the |
|
|
| | | | | address group (255 characters limit). |
|
|
+-------------------+---------+-------+------+---------------------------------------+
|
|
| project_id | uuid-str| No | CR | Owner of the address group. Only |
|
|
| | | | | admin users can specify a project |
|
|
| | | | | identifier other than their own. |
|
|
+-------------------+---------+-------+------+---------------------------------------+
|
|
| addresses | List | Yes | CRU | Array of address. It supports both |
|
|
| | | | | CIDR and IP range objects. |
|
|
| | | | | An example of addresses: |
|
|
| | | | | ["132.168.4.12/24", |
|
|
| | | | | "132.168.5.12-132.168.5.24", |
|
|
| | | | | "2001::db8::f00/64"] |
|
|
+-------------------+---------+-------+------+---------------------------------------+
|
|
|
|
|
|
|
|
|
List address groups
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
Lists address groups.
|
|
|
|
+----------------+------------------------------------------------+
|
|
| Request Type | ``GET`` |
|
|
+----------------+------------------------------------------------+
|
|
| Endpoint | ``/v2.0/address-groups`` |
|
|
+----------------+---------+--------------------------------------+
|
|
| | Success | 200 |
|
|
| Response Codes +---------+--------------------------------------+
|
|
| | Error | Unauthorized(401) |
|
|
+----------------+---------+--------------------------------------+
|
|
|
|
|
|
|
|
|
**Example List address groups: JSON request**
|
|
|
|
.. code::
|
|
|
|
GET /v2.0/address-groups
|
|
User-Agent: python-neutronclient
|
|
Accept: application/json
|
|
|
|
**Example List address groups: JSON response**
|
|
|
|
|
|
.. code::
|
|
|
|
{
|
|
"address_groups": [
|
|
{
|
|
"description": "",
|
|
"id": "8722e0e0-9cc9-4490-9660-8c9a5732fbb0",
|
|
"name": "ADDR_GP_1",
|
|
"project_id": "45977fa2dbd7482098dd68d0d8970117",
|
|
"addresses": [
|
|
"132.168.4.12/24",
|
|
"132.168.5.12-132.168.5.24",
|
|
"2001::db8::f00/64"
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
Show address group details
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Shows address group details.
|
|
|
|
+----------------+----------------------------------------------------+
|
|
| Request Type | ``GET`` |
|
|
+----------------+----------------------------------------------------+
|
|
| Endpoint | ``/v2.0/address-groups/<address_group_id>`` |
|
|
+----------------+---------+------------------------------------------+
|
|
| | Success | 200 |
|
|
| Response Codes +---------+------------------------------------------+
|
|
| | Error | Unauthorized(401), Not Found (404) |
|
|
+----------------+---------+------------------------------------------+
|
|
|
|
|
|
|
|
|
**Example Show address group: JSON request**
|
|
|
|
.. code::
|
|
|
|
GET /v2.0/address-groups/8722e0e0-9cc9-4490-9660-8c9a5732fbb0
|
|
User-Agent: python-neutronclient
|
|
Accept: application/json
|
|
|
|
|
|
**Example Show address group: JSON response**
|
|
|
|
.. code::
|
|
|
|
{
|
|
"address_group": {
|
|
"description": "",
|
|
"id": "8722e0e0-9cc9-4490-9660-8c9a5732fbb0",
|
|
"name": "ADDR_GP_1",
|
|
"project_id": "45977fa2dbd7482098dd68d0d8970117",
|
|
"addresses": [
|
|
"132.168.4.12/24",
|
|
"132.168.5.12-132.168.5.24",
|
|
"2001::db8::f00/64"
|
|
]
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Create address group
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Creates an address group.
|
|
|
|
+----------------+------------------------------------------------+
|
|
| Request Type | ``POST`` |
|
|
+----------------+------------------------------------------------+
|
|
| Endpoint | ``/v2.0/address-groups/`` |
|
|
+----------------+---------+--------------------------------------+
|
|
| | Success | 201 |
|
|
| Response Codes +---------+--------------------------------------+
|
|
| | Error | Unauthorized(401), Bad Request(400) |
|
|
+----------------+---------+--------------------------------------+
|
|
|
|
|
|
|
|
|
**Example Create address group: JSON request**
|
|
|
|
.. code::
|
|
|
|
POST /v2.0/address-groups
|
|
User-Agent: python-neutronclient
|
|
Accept: application/json
|
|
|
|
.. code::
|
|
|
|
{
|
|
"address_group": {
|
|
"name": "ADDR_GP_1",
|
|
"addresses": [
|
|
"132.168.4.12/24",
|
|
"132.168.5.12-132.168.5.24",
|
|
"2001::db8::f00/64"
|
|
]
|
|
}
|
|
}
|
|
|
|
**Example Create address group: JSON response**
|
|
|
|
.. code::
|
|
|
|
HTTP/1.1 201 Created
|
|
Content-Type: application/json; charset=UTF-8
|
|
|
|
.. code::
|
|
|
|
{
|
|
"address_group": {
|
|
"description": "",
|
|
"id": "8722e0e0-9cc9-4490-9660-8c9a5732fbb0",
|
|
"name": "ADDR_GP_1",
|
|
"project_id": "45977fa2dbd7482098dd68d0d8970117",
|
|
"addresses": [
|
|
"132.168.4.12/24",
|
|
"132.168.5.12-132.168.5.24",
|
|
"2001::db8::f00/64"
|
|
]
|
|
}
|
|
}
|
|
|
|
|
|
Update address group
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Updates an address group. To update addresses, use the add addresses and
|
|
remove addresses operations.
|
|
|
|
+----------------+----------------------------------------------------+
|
|
| Request Type | ``PUT`` |
|
|
+----------------+----------------------------------------------------+
|
|
| Endpoint | ``/v2.0/address-groups/<address_group_id>`` |
|
|
+----------------+---------+------------------------------------------+
|
|
| | Success | 200 |
|
|
| Response Codes +---------+------------------------------------------+
|
|
| | Error | Unauthorized(401), Bad Request(400) \ |
|
|
| | | Not Found(404) |
|
|
+----------------+---------+------------------------------------------+
|
|
|
|
|
|
|
|
|
**Example Update address group: JSON request**
|
|
|
|
.. code::
|
|
|
|
PUT /v2.0/address-groups/8722e0e0-9cc9-4490-9660-8c9a5732fbb0
|
|
User-Agent: python-neutronclient
|
|
Accept: application/json
|
|
|
|
.. code::
|
|
|
|
{
|
|
"address_group": {
|
|
"description": "new description",
|
|
"name": "new name"
|
|
}
|
|
}
|
|
|
|
|
|
**Example Update address group: JSON response**
|
|
|
|
.. code::
|
|
|
|
HTTP/1.1 200 OK
|
|
Content-Type: application/json; charset=UTF-8
|
|
|
|
.. code::
|
|
|
|
{
|
|
"address_group": {
|
|
"description": "new description",
|
|
"id": "8722e0e0-9cc9-4490-9660-8c9a5732fbb0",
|
|
"name": "new name",
|
|
"project_id": "45977fa2dbd7482098dd68d0d8970117",
|
|
"addresses": [
|
|
"132.168.4.12/24",
|
|
"132.168.5.12-132.168.5.24",
|
|
"2001::db8::f00/64"
|
|
]
|
|
}
|
|
}
|
|
|
|
|
|
Add addresses to address group
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Add addresses to an existing address group.
|
|
|
|
+----------------+------------------------------------------------------------------+
|
|
| Request Type | ``PUT`` |
|
|
+----------------+------------------------------------------------------------------+
|
|
| Endpoint | ``/v2.0/address-groups/<address_group_id>/add_addresses`` |
|
|
+----------------+---------+--------------------------------------------------------+
|
|
| | Success | 200 |
|
|
| Response Codes +---------+--------------------------------------------------------+
|
|
| | Error | Unauthorized(401), Bad Request(400), Not Found(404) |
|
|
+----------------+---------+--------------------------------------------------------+
|
|
|
|
|
|
|
|
|
**Example Update addresses: JSON request**
|
|
|
|
.. code::
|
|
|
|
PUT /v2.0/address-groups/8722e0e0-9cc9-4490-9660-8c9a5732fbb0/add_addresses
|
|
User-Agent: python-neutronclient
|
|
Accept: application/json
|
|
|
|
.. code::
|
|
|
|
{
|
|
"addresses": [
|
|
"10.0.0.1/32",
|
|
"2001:3889:120:fe42::/64"
|
|
]
|
|
}
|
|
|
|
|
|
**Example Update addresses: JSON response**
|
|
|
|
.. code::
|
|
|
|
HTTP/1.1 200 OK
|
|
Content-Type: application/json; charset=UTF-8
|
|
|
|
.. code::
|
|
|
|
{
|
|
"address_group": {
|
|
"description": "",
|
|
"id": "8722e0e0-9cc9-4490-9660-8c9a5732fbb0",
|
|
"name": "ADDR_GP_1",
|
|
"project_id": "45977fa2dbd7482098dd68d0d8970117",
|
|
"addresses": [
|
|
"132.168.4.12/24",
|
|
"132.168.5.12-132.168.5.24",
|
|
"10.0.0.1/32",
|
|
"2001::db8::f00/64",
|
|
"2001:3889:120:fe42::/64"
|
|
]
|
|
}
|
|
}
|
|
|
|
Remove addresses from address group
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Remove addresses from an existing address group.
|
|
|
|
+----------------+------------------------------------------------------------------+
|
|
| Request Type | ``PUT`` |
|
|
+----------------+------------------------------------------------------------------+
|
|
| Endpoint | ``/v2.0/address-groups/<address_group_id>/remove_addresses`` |
|
|
+----------------+---------+--------------------------------------------------------+
|
|
| | Success | 200 |
|
|
| Response Codes +---------+--------------------------------------------------------+
|
|
| | Error | Unauthorized(401), Bad Request(400), Not Found(404) |
|
|
+----------------+---------+--------------------------------------------------------+
|
|
|
|
|
|
|
|
|
**Example Remove addresses: JSON request**
|
|
|
|
.. code::
|
|
|
|
PUT /v2.0/address-groups/8722e0e0-9cc9-4490-9660-8c9a5732fbb0/remove_addresses
|
|
User-Agent: python-neutronclient
|
|
Accept: application/json
|
|
|
|
.. code::
|
|
|
|
{
|
|
"addresses": [
|
|
"132.168.4.12/24",
|
|
"2001::db8::f00/64"
|
|
]
|
|
}
|
|
|
|
|
|
**Example Remove addresses: JSON response**
|
|
|
|
.. code::
|
|
|
|
HTTP/1.1 200 OK
|
|
Content-Type: application/json; charset=UTF-8
|
|
|
|
.. code::
|
|
|
|
{
|
|
"address_group": {
|
|
"description": "",
|
|
"id": "8722e0e0-9cc9-4490-9660-8c9a5732fbb0",
|
|
"name": "ADDR_GP_1",
|
|
"project_id": "45977fa2dbd7482098dd68d0d8970117",
|
|
"addresses": [
|
|
"132.168.5.12-132.168.5.24"
|
|
]
|
|
}
|
|
}
|
|
|
|
Delete address group
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Deletes an address group.
|
|
|
|
This operation does not return a response body.
|
|
|
|
+----------------+----------------------------------------------------+
|
|
| Request Type | ``DELETE`` |
|
|
+----------------+----------------------------------------------------+
|
|
| Endpoint | ``/v2.0/address-groups/<address_group_id>`` |
|
|
+----------------+---------+------------------------------------------+
|
|
| | Success | 204 |
|
|
| Response Codes +---------+------------------------------------------+
|
|
| | Error | Unauthorized(401), Not Found(404) |
|
|
| | | Conflict(409) The Conflict error response|
|
|
| | | is returned when an operation is |
|
|
| | | performed while address group is in use. |
|
|
+----------------+---------+------------------------------------------+
|
|
|
|
|
|
|
|
|
**Example Delete address group: JSON request**
|
|
|
|
.. code::
|
|
|
|
DELETE /v2.0/address-groups/8722e0e0-9cc9-4490-9660-8c9a5732fbb0
|
|
User-Agent: python-neutronclient
|
|
Accept: application/json
|
|
|
|
**Example Delete address group: JSON response**
|
|
|
|
.. code::
|
|
|
|
HTTP/1.1 204 No Content
|
|
Content-Length: 0
|
|
|
|
|
|
Changes to the existing security group rules API
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
List security group rules
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Lists security group rules.
|
|
|
|
Remote address group id field will be added to response.
|
|
|
|
.. code::
|
|
|
|
GET /v2.0/security-group-rules
|
|
User-Agent: python-neutronclient
|
|
Accept: application/json
|
|
|
|
|
|
**Example List security group rules: JSON response**
|
|
|
|
|
|
.. code::
|
|
|
|
{
|
|
"security_group_rules": [
|
|
{
|
|
"direction": "ingress",
|
|
"ethertype": "IPv4",
|
|
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c",
|
|
"port_range_max": null,
|
|
"port_range_min": null,
|
|
"protocol": null,
|
|
"remote_group_id": null,
|
|
"remote_ip_prefix": null,
|
|
"remote_address_group_id": "8722e0e0-9cc9-4490-9660-8c9a5732fbb0",
|
|
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
|
|
"project_id": "e4f50856753b4dc6afee5fa6b9b6c550",
|
|
"revision_number": 1,
|
|
"created_at": "2018-03-19T19:16:56Z",
|
|
"updated_at": "2018-03-19T19:16:56Z",
|
|
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550",
|
|
"description": ""
|
|
}
|
|
]
|
|
}
|
|
|
|
Show security group rule details
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Shows security group rule details.
|
|
|
|
Remote address group id field will be added to response.
|
|
|
|
**Example Show security group rule: JSON request**
|
|
|
|
.. code::
|
|
|
|
GET /v2.0/security-group-rules/f7d45c89-008e-4bab-88ad-d6811724c51c
|
|
User-Agent: python-neutronclient
|
|
Accept: application/json
|
|
|
|
|
|
**Example Show security group rule: JSON response**
|
|
|
|
.. code::
|
|
|
|
{
|
|
"security_group_rule": {
|
|
"direction": "ingress",
|
|
"ethertype": "IPv4",
|
|
"id": "f7d45c89-008e-4bab-88ad-d6811724c51c",
|
|
"port_range_max": null,
|
|
"port_range_min": null,
|
|
"protocol": null,
|
|
"remote_group_id": null,
|
|
"remote_ip_prefix": null,
|
|
"remote_address_group_id": "8722e0e0-9cc9-4490-9660-8c9a5732fbb0",
|
|
"security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
|
|
"project_id": "e4f50856753b4dc6afee5fa6b9b6c550",
|
|
"revision_number": 1,
|
|
"created_at": "2018-03-19T19:16:56Z",
|
|
"updated_at": "2018-03-19T19:16:56Z",
|
|
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550",
|
|
"description": ""
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Create security group rule
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Creates a security group rule with a remote address group.
|
|
|
|
Note: At most one of remote-group, remote-ip and remote-address-group can be
|
|
specified. The rule is matched when the remote IP address in the packet matches
|
|
any one of: remote_ip_address, one of the IP addresses in the address group,
|
|
or an IP address of one of the ports in the remote security group.
|
|
|
|
**Example Create security group rule: JSON request**
|
|
|
|
.. code::
|
|
|
|
POST /v2.0/security-group-rules
|
|
User-Agent: python-neutronclient
|
|
Accept: application/json
|
|
|
|
.. code::
|
|
|
|
{
|
|
"security_group_rule": {
|
|
"direction": "ingress",
|
|
"port_range_min": "80",
|
|
"ethertype": "IPv4",
|
|
"port_range_max": "80",
|
|
"protocol": "tcp",
|
|
"remote_address_group_id": "8722e0e0-9cc9-4490-9660-8c9a5732fbb0",
|
|
"security_group_id": "a7734e61-b545-452d-a3cd-0189cbd9747a"
|
|
}
|
|
}
|
|
|
|
**Example Create security group rule: JSON response**
|
|
|
|
.. code::
|
|
|
|
HTTP/1.1 201 Created
|
|
Content-Type: application/json; charset=UTF-8
|
|
|
|
.. code::
|
|
|
|
{
|
|
"security_group_rule": {
|
|
"direction": "ingress",
|
|
"ethertype": "IPv4",
|
|
"id": "2bc0accf-312e-429a-956e-e4407625eb62",
|
|
"port_range_max": 80,
|
|
"port_range_min": 80,
|
|
"protocol": "tcp",
|
|
"remote_ip_prefix": null,
|
|
"remote_group_id": null,
|
|
"remote_address_group_id": "8722e0e0-9cc9-4490-9660-8c9a5732fbb0",
|
|
"security_group_id": "a7734e61-b545-452d-a3cd-0189cbd9747a",
|
|
"project_id": "e4f50856753b4dc6afee5fa6b9b6c550",
|
|
"revision_number": 1,
|
|
"tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550",
|
|
"created_at": "2018-03-19T19:16:56Z",
|
|
"updated_at": "2018-03-19T19:16:56Z",
|
|
"description": ""
|
|
}
|
|
}
|
|
|
|
|
|
Data Model Impact
|
|
-----------------
|
|
|
|
The following are the backend database tables for the REST API proposed above.
|
|
|
|
|
|
|
| **Address Groups**
|
|
|
|
+-------------------+---------+-------+------+----------------------------------------+
|
|
| Attribute | Type | Req | CRUD | Description |
|
|
+===================+=========+=======+======+========================================+
|
|
| id | uuid-str| N/A | R | Unique identifier for the |
|
|
| | | | | address_group object. |
|
|
+-------------------+---------+-------+------+----------------------------------------+
|
|
| name | String | No | CRU | Human readable name for the address |
|
|
| | | | | group (255 characters limit). Does not |
|
|
| | | | | have to be unique. |
|
|
+-------------------+---------+-------+------+----------------------------------------+
|
|
| description | String | No | CRU | Human readable description for the |
|
|
| | | | | address group (255 characters limit). |
|
|
+-------------------+---------+-------+------+----------------------------------------+
|
|
| project_id | uuid-str| Yes | CR | Owner of the address group. Only |
|
|
| | | | | admin users can specify a project |
|
|
| | | | | identifier other than their own. |
|
|
+-------------------+---------+-------+------+----------------------------------------+
|
|
|
|
|
|
|
|
|
| **Address Group Address Associations**
|
|
|
|
+-------------------+---------+-------+------+----------------------------------------+
|
|
| Attribute | Type | Req | CRUD | Description |
|
|
+===================+=========+=======+======+========================================+
|
|
| address_group_id | uuid-str| No | CRU | UUID of address group. |
|
|
+-------------------+---------+-------+------+----------------------------------------+
|
|
| address | String | No | CRU | Address that has to be associated to |
|
|
| | | | | the address group. |
|
|
+-------------------+---------+-------+------+----------------------------------------+
|
|
|
|
|
|
|
|
|
| **Security Group Rules**
|
|
|
|
Attribute remote_address_group_id will be added to security group rules table
|
|
|
|
+------------------------+------------+-----+------+---------------------------------------+
|
|
| Attribute | Type | Req | CRUD | Description |
|
|
+========================+============+=====+======+=======================================+
|
|
| remote_address | String | No | CRU | When a remote_address_group is |
|
|
| _group_id | | | | specified, it is matched when the |
|
|
| | | | | remote IP address in the packet |
|
|
| | | | | matches one of the IP addresses in |
|
|
| | | | | the address group. This is exclusive |
|
|
| | | | | with remote_ip_prefix and |
|
|
| | | | | remote_group_id. |
|
|
+------------------------+------------+-----+------+---------------------------------------+
|
|
|
|
|
|
Implementation
|
|
==============
|
|
|
|
Assignee(s)
|
|
-----------
|
|
|
|
* Hang Yang
|
|
|
|
Work Items
|
|
----------
|
|
|
|
* REST API update
|
|
* DB schema update
|
|
* CLI update
|
|
* Open vSwitch and iptables firewall drivers update
|
|
* RBAC support for address groups
|
|
* Documentation update
|
|
|
|
Testing
|
|
=======
|
|
|
|
Tempest Tests
|
|
-------------
|
|
|
|
* DB mixin and schema tests
|
|
* Tempest tests
|
|
* CLI tests
|
|
|
|
Functional Tests
|
|
----------------
|
|
|
|
* New tests need to be written
|
|
|
|
API Tests
|
|
---------
|
|
|
|
* REST API and attributes validation tests
|
|
|
|
Documentation Impact
|
|
====================
|
|
|
|
User Documentation
|
|
------------------
|
|
|
|
* Neutron CLI and API documentation have to be modified.
|
|
|
|
Developer Documentation
|
|
-----------------------
|
|
|
|
* Neutron API devref and documentation need to be updated.
|
|
|
|
References
|
|
==========
|
|
|
|
[1] https://specs.openstack.org/openstack/neutron-specs/specs/rocky/fwaas-2.0-address-groups-support.html
|
|
|
|
[2] https://docs.openstack.org/api-ref/network/v2/#security-group-rules-security-group-rules
|