安全组规则中地址组支持

https://bugs.launchpad.net/neutron/+bug/1592028

本规范描述了如何在 Neutron 安全组规则中支持地址组(IP 地址块的组)。地址组的概念是在 FWaaS v2.0 中引入的,但尚未实现 [1]。

问题描述

Neutron 安全组规则当前支持使用 IP 地址块或安全组作为网络访问规则的远程端。在实际使用中,OpenStack 云可能需要实例与未由 OpenStack 配置的服务之间的连接。并且每个服务也可能有多个不连续的端点地址。为了允许连接,需要为每个外部地址创建一个规则,这可能非常繁琐且难以维护,因为外部地址的数量可能很大。

提议的变更

添加一个 API 来聚合 IP 地址块到地址组对象中,该对象稍后可以在创建安全组规则时引用。因此,当需要允许连接到多个外部服务地址时,可以有效地减少安全组规则的数量。当地址组中的 IP 地址更新时,更改也会反映在关联的安全组规则中。

REST API 影响

新的地址组 API

属性

类型

必需

CRUD

描述

id

uuid-str

N/A

R

地址组对象的唯一标识符。

name

字符串

CRU

地址组的人性化名称(限制为 255 个字符)。 不必唯一。

description

字符串

CRU

地址组的人性化描述(限制为 255 个字符)。

project_id

uuid-str

CR

地址组的所有者。 只有管理员用户才能指定与其自身不同的项目标识符。

addresses

列表

CRU

地址数组。它支持 CIDR 和 IP 范围对象。地址示例:[“132.168.4.12/24”, “132.168.5.12-132.168.5.24”, “2001::db8::f00/64”]


列出地址组

列出地址组。

请求类型

GET

端点

/v2.0/address-groups

响应代码

成功

200

Error

Unauthorized(401)


示例列出地址组:JSON 请求

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

示例列出地址组:JSON 响应

{
    "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"
            ]
        }
    ]
}
显示地址组详细信息

显示地址组详细信息。

请求类型

GET

端点

/v2.0/address-groups/<address_group_id>

响应代码

成功

200

Error

Unauthorized(401), Not Found (404)


示例显示地址组:JSON 请求

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

示例显示地址组:JSON 响应

{
   "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"
        ]
    }
}
创建地址组

创建地址组。

请求类型

POST

端点

/v2.0/address-groups/

响应代码

成功

201

Error

Unauthorized(401), Bad Request(400)


示例创建地址组:JSON 请求

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"
        ]
    }
}

示例创建地址组:JSON 响应

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"
        ]
    }
}
更新地址组

更新地址组。要更新地址,请使用添加地址和删除地址操作。

请求类型

PUT

端点

/v2.0/address-groups/<address_group_id>

响应代码

成功

200

Error

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


示例更新地址组:JSON 请求

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

示例更新地址组:JSON 响应

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"
        ]
    }
}
向地址组添加地址

向现有的地址组添加地址。

请求类型

PUT

端点

/v2.0/address-groups/<address_group_id>/add_addresses

响应代码

成功

200

Error

未授权(401),错误请求(400),未找到(404)


示例 更新地址: JSON 请求

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"
    ]
}

示例 更新地址: JSON 响应

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"
        ]
    }
}
从地址组删除地址

从现有的地址组删除地址。

请求类型

PUT

端点

/v2.0/address-groups/<address_group_id>/remove_addresses

响应代码

成功

200

Error

未授权(401),错误请求(400),未找到(404)


示例 删除地址: JSON 请求

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"
    ]
}

示例 删除地址: JSON 响应

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

端点

/v2.0/address-groups/<address_group_id>

响应代码

成功

204

Error

Unauthorized(401), Not Found(404) Conflict(409) 当在地址组使用时执行操作时,将返回 Conflict 错误响应。


示例删除地址组:JSON 请求

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

示例删除地址组:JSON 响应

HTTP/1.1 204 No Content
Content-Length: 0

对现有安全组规则 API 的更改

列出安全组规则

列出安全组规则。

将在响应中添加远程地址组 ID 字段。

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

示例 列出安全组规则: JSON 响应

{
    "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": ""
        }
    ]
}
显示安全组规则详细信息

显示安全组规则详细信息。

将在响应中添加远程地址组 ID 字段。

示例 显示安全组规则: JSON 请求

GET /v2.0/security-group-rules/f7d45c89-008e-4bab-88ad-d6811724c51c
User-Agent: python-neutronclient
Accept: application/json

示例 显示安全组规则: JSON 响应

{
    "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": ""
    }
}
创建安全组规则

使用远程地址组创建一个安全组规则。

注意:remote-group、remote-ip 和 remote-address-group 中最多只能指定一个。当数据包中的远程 IP 地址与以下任一匹配时,规则匹配:remote_ip_address、地址组中的一个 IP 地址,或远程安全组中的一个端口的 IP 地址。

示例 创建安全组规则: JSON 请求

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

示例 创建安全组规则: JSON 响应

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": ""
    }
}

数据模型影响

以下是上述 REST API 的后端数据库表。


地址组

属性

类型

必需

CRUD

描述

id

uuid-str

N/A

R

地址组对象的唯一标识符。

name

字符串

CRU

地址组的人性化名称(限制为 255 个字符)。 不必唯一。

description

字符串

CRU

地址组的人性化描述(限制为 255 个字符)。

project_id

uuid-str

CR

地址组的所有者。 只有管理员用户才能指定与其自身不同的项目标识符。


地址组地址关联

属性

类型

必需

CRUD

描述

address_group_id

uuid-str

CRU

地址组的 UUID。

address

字符串

CRU

必须与地址组关联的地址。


安全组规则

remote_address_group_id 属性将添加到安全组规则表

属性

类型

必需

CRUD

描述

remote_address _group_id

字符串

CRU

当指定 remote_address_group 时,如果数据包中的远程 IP 地址与地址组中的一个 IP 地址匹配,则匹配。这与 remote_ip_prefix 和 remote_group_id 互斥。

实现

负责人

  • 杨航

工作项

  • REST API 更新

  • 数据库模式更新

  • CLI 更新

  • Open vSwitch 和 iptables 防火墙驱动程序更新

  • 地址组的 RBAC 支持

  • 文档更新

测试

Tempest 测试

  • DB mixin 和模式测试

  • Tempest 测试

  • CLI 测试

功能测试

  • 需要编写新的测试

API 测试

  • REST API 和属性验证测试

文档影响

用户文档

  • 需要修改 Neutron CLI 和 API 文档。

开发人员文档

  • 需要更新 Neutron API devref 和文档。

参考资料

[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