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

Response Codes

Success

200

Error

Unauthorized(401)


Example List address groups: JSON request

GET /v2.0/address-groups
User-Agent: python-neutronclient
Accept: application/json

Example List address groups: JSON response

{
    "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>

Response Codes

Success

200

Error

Unauthorized(401), Not Found (404)


Example Show address group: JSON request

GET /v2.0/address-groups/8722e0e0-9cc9-4490-9660-8c9a5732fbb0
User-Agent: python-neutronclient
Accept: application/json

Example Show address group: JSON response

{
   "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/

Response Codes

Success

201

Error

Unauthorized(401), Bad Request(400)


Example Create address group: JSON request

POST /v2.0/address-groups
User-Agent: python-neutronclient
Accept: application/json
{
    "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

HTTP/1.1 201 Created
Content-Type: application/json; charset=UTF-8
{
   "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>

Response Codes

Success

200

Error

Unauthorized(401), Bad Request(400) Not Found(404)


Example Update address group: JSON request

PUT /v2.0/address-groups/8722e0e0-9cc9-4490-9660-8c9a5732fbb0
User-Agent: python-neutronclient
Accept: application/json
{
    "address_group": {
        "description": "new description",
        "name": "new name"
    }
}

Example Update address group: JSON response

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
{
   "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

Response Codes

Success

200

Error

Unauthorized(401), Bad Request(400), Not Found(404)


Example Update addresses: JSON request

PUT /v2.0/address-groups/8722e0e0-9cc9-4490-9660-8c9a5732fbb0/add_addresses
User-Agent: python-neutronclient
Accept: application/json
{
    "addresses": [
       "10.0.0.1/32",
       "2001:3889:120:fe42::/64"
    ]
}

Example Update addresses: JSON response

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
{
   "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

Response Codes

Success

200

Error

Unauthorized(401), Bad Request(400), Not Found(404)


Example Remove addresses: JSON request

PUT /v2.0/address-groups/8722e0e0-9cc9-4490-9660-8c9a5732fbb0/remove_addresses
User-Agent: python-neutronclient
Accept: application/json
{
    "addresses": [
       "132.168.4.12/24",
       "2001::db8::f00/64"
    ]
}

Example Remove addresses: JSON response

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
{
   "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>

Response Codes

Success

204

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

DELETE /v2.0/address-groups/8722e0e0-9cc9-4490-9660-8c9a5732fbb0
User-Agent: python-neutronclient
Accept: application/json

Example Delete address group: JSON response

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.

GET /v2.0/security-group-rules
User-Agent: python-neutronclient
Accept: application/json

Example List security group rules: JSON response

{
    "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

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

{
    "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

POST /v2.0/security-group-rules
User-Agent: python-neutronclient
Accept: application/json
{
    "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

HTTP/1.1 201 Created
Content-Type: application/json; charset=UTF-8
{
    "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 _group_id

String

No

CRU

When a remote_address_group is 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