From 35fe0e3b0d12521d63ad36df11000311b2beaa02 Mon Sep 17 00:00:00 2001 From: Hang Yang Date: Mon, 20 Apr 2020 13:57:07 -0500 Subject: [PATCH] Support address groups in security group rules This specification describes how to support address groups in security group rules. Change-Id: Ib58afde9ed58092ffbc94f7d522d5f5d034b832b Related-Bug: #1592028 --- ...-groups-support-in-security-group-rule.rst | 708 ++++++++++++++++++ 1 file changed, 708 insertions(+) create mode 100644 specs/victoria/address-groups-support-in-security-group-rule.rst diff --git a/specs/victoria/address-groups-support-in-security-group-rule.rst b/specs/victoria/address-groups-support-in-security-group-rule.rst new file mode 100644 index 000000000..9da0a7b79 --- /dev/null +++ b/specs/victoria/address-groups-support-in-security-group-rule.rst @@ -0,0 +1,708 @@ +.. + 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/`` | + +----------------+---------+------------------------------------------+ + | | 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/`` | + +----------------+---------+------------------------------------------+ + | | 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//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//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/`` | + +----------------+---------+------------------------------------------+ + | | 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