访问控制列表 (ACL)

通常,要创建、读取和修改容器和对象,您必须在与帐户关联的项目上拥有适当的角色,即您必须是帐户的所有者。但是,所有者可以使用访问控制列表 (ACL) 授予其他用户访问权限。

ACL 有两种类型

  • 容器 ACL。这些在容器上指定,仅适用于该容器及其中的对象。

  • 帐户 ACL。这些在帐户级别指定,适用于帐户中的所有容器和对象。

容器 ACL

容器 ACL 存储在 X-Container-WriteX-Container-Read 元数据中。ACL 的范围限制在设置元数据的容器及其中的对象。此外

  • X-Container-Write 授予在容器内执行 PUT、POST 和 DELETE 操作的能力。它不授予对容器本身执行 POST 或 DELETE 操作的能力。某些 ACL 元素还授予对容器执行 HEAD 或 GET 操作的能力。

  • X-Container-Read 授予在容器内执行 GET 和 HEAD 操作的能力。某些 ACL 元素还授予对容器本身执行 HEAD 或 GET 操作的能力。但是,容器 ACL 不允许访问特权元数据(例如 X-Container-Sync-Key)。

容器 ACL 使用“V1”ACL 语法,这是一种逗号分隔的元素字符串,如下例所示

.r:*,.rlistings,7ec59e87c6584c348b563254aae4c221:*

元素之间可能存在空格,如下例所示

.r : *, .rlistings, 7ec59e87c6584c348b563254aae4c221:*

但是,这些空格将从存储在 X-Container-WriteX-Container-Read 元数据中的值中删除。此外,.r: 字符串可以写成 .referrer:,但存储为 .r:

虽然所有身份验证系统都使用相同的语法,但由于不同身份验证系统使用的概念不同,某些元素的含义也不同,如以下部分所述

常用 ACL 元素

下表描述了 Keystone 身份验证和 TempAuth 都支持的 ACL 元素。这些元素应仅与 X-Container-Read 一起使用(.rlistings 除外,如果与 X-Container-Write 一起使用,将发生错误)

元素

描述

.r:*

任何用户都可以访问对象。请求中不需要令牌。

.r:<referrer>

引用者被授予对对象的访问权限。引用者由请求中的 Referer 请求标头标识。不需要令牌。

.r:-<referrer>

支持这种语法(在引用者前面加上“-”)。但是,如果另一个元素(例如 .r:*)授予访问权限,则它不会拒绝访问。

.rlistings

任何用户都可以对容器执行 HEAD 或 GET 操作,前提是用户也具有对对象的读取访问权限(例如,也具有 .r:*.r:<referrer>)。不需要令牌。

Keystone 身份验证 ACL 元素

下表描述了仅受 Keystone 身份验证支持的 ACL 元素。Keystone 身份验证还支持 常用 ACL 元素 中描述的元素。

必须在请求中包含令牌,才能使这些 ACL 元素生效。

元素

描述

<project-id>:<user-id>

如果请求中包含作用域限定为该项目的令牌,则指定的用户被授予访问权限。当在 X-Container-Read 中使用时,也授予对容器的访问权限。

<project-id>:*

具有指定 Keystone 项目中角色的任何用户都可以访问。必须在请求中包含作用域限定为该项目的令牌。当在 X-Container-Read 中使用时,也授予对容器的访问权限。

*:<user-id>

指定的用户具有访问权限。必须在请求中包含该用户的令牌(作用域限定为任何项目)。当在 X-Container-Read 中使用时,也授予对容器的访问权限。

*:*

任何用户都可以访问。当在 X-Container-Read 中使用时,也授予对容器的访问权限。*:* 元素与 .r:* 元素不同,因为 *:* 需要在请求中包含有效的令牌,而 .r:* 不需要令牌。此外,.r:* 不授予对容器列表的访问权限。

<role_name>

在存储容器的项目上分配了指定角色 name 的用户被授予访问权限。必须在请求中包含作用域限定为该项目的用户令牌。当在 X-Container-Read 中使用时,也授予对容器的访问权限。

注意

由于 Keystone 中引入了域,名称不再全局唯一,因此不再使用 Keystone 项目(租户)或用户 名称(即 <project-name>:<user-name>)。您应该使用用户和项目 ID 代替。

为了保持向后兼容性,如果可以确定被授予者项目、被授予者用户和正在访问的项目要么尚未在域中(例如,X-Auth-Token 已通过 Keystone V2 API 获取),要么都在迁移到传统帐户的默认域中,则 keystoneauth 将授予使用名称的 ACL。

TempAuth ACL 元素

下表描述了仅受 TempAuth 支持的 ACL 元素。TempAuth 身份验证还支持 常用 ACL 元素 中描述的元素。

元素

描述

<user-name>

指定的用户被授予访问权限。不支持通配符 (“*”) 字符。必须在请求中包含来自该用户的令牌。

容器 ACL 示例

可以通过在对容器 URL 的 PUT 或 POST 请求中包含 X-Container-Write 和/或 X-Container-Read 标头来设置容器 ACL。以下示例使用 swift 命令行客户端,该客户端通过其 --write-acl--read-acl 选项支持设置这些标头。

示例:公共容器

以下允许任何人列出 www 容器中的对象并下载对象。用户不需要在请求中包含令牌。此 ACL 通常被称为使容器“公共”。当与 StaticWeb 一起使用时很有用

swift post www --read-acl ".r:*,.rlistings"

示例:共享可写容器

以下允许任何人上传或下载对象。但是,要下载对象,必须知道对象的确切名称,因为用户无法列出容器中的对象。用户必须在上传请求中包含 Keystone 令牌。但是,它不需要作用域限定为与容器关联的项目

swift post www --read-acl ".r:*" --write-acl "*:*"

示例:与项目成员共享容器

以下允许 77b8f82565f14814bece56e50c4c240f 项目的任何成员上传和下载对象或列出 www 容器的内容。必须在请求中包含作用域限定为 77b8f82565f14814bece56e50c4c240f 项目的令牌

swift post www --read-acl "77b8f82565f14814bece56e50c4c240f:*" \
               --write-acl "77b8f82565f14814bece56e50c4c240f:*"

示例:与具有指定角色的用户共享容器

以下允许在存储 www 容器的项目上分配了 my_read_access_role 角色的任何用户下载对象或列出 www 容器的内容。必须在下载或列表请求中包含作用域限定为该项目的用户令牌

swift post www --read-acl "my_read_access_role"

示例:允许引用域下载对象

以下允许来自 example.com 域的任何请求访问容器中的对象

swift post www --read-acl ".r:.example.com"

但是,用户的请求 必须 包含适当的 Referer 标头,如本示例请求所示

curl -i $publicURL/www/document --head -H "Referer: http://www.example.com/index.html"

注意

许多浏览器都在请求中包含 Referer 标头。但是,由于很容易创建一个在 Referer 标头中具有任何所需值的请求,因此引用者 ACL 具有非常弱的安全保障。

示例:与另一个用户共享容器

与另一个用户共享容器需要了解有关用户的几个参数。

共享用户必须知道

  • 另一个用户的 OpenStack 用户 ID

共享用户必须告知另一个用户

  • 共享容器的名称

  • the OS_STORAGE_URL

通常,OS_STORAGE_URL 不直接暴露给用户,因为 swift 客户端 默认情况下会自动根据用户凭据构造 OS_STORAGE_URL

我们假设当前目录中有两个用户的客户端环境脚本 sharing.openrcother.openrc

The sharing.openrc 应该类似于以下内容

export OS_USERNAME=sharing
# WARNING: Save the password in clear text only for testing purposes
export OS_PASSWORD=password
export OS_TENANT_NAME=projectName
export OS_AUTH_URL=https://identityHost:portNumber/v2.0
# The following lines can be omitted
export OS_TENANT_ID=tenantIDString
export OS_REGION_NAME=regionName
export OS_CACERT=/path/to/cacertFile

The other.openrc 应该类似于以下内容

export OS_USERNAME=other
# WARNING: Save the password in clear text only for testing purposes
export OS_PASSWORD=otherPassword
export OS_TENANT_NAME=otherProjectName
export OS_AUTH_URL=https://identityHost:portNumber/v2.0
# The following lines can be omitted
export OS_TENANT_ID=tenantIDString
export OS_REGION_NAME=regionName
export OS_CACERT=/path/to/cacertFile

有关更多信息,请参阅 使用 OpenStack RC 文件

首先我们找出另一个用户的 ID

. other.openrc
OUID="$(openstack user show --format json "${OS_USERNAME}" | jq -r .id)"

或者

. other.openrc
OUID="$(openstack token issue -f json | jq -r .user_id)"

然后我们找出共享用户的存储 URL

sharing.openrc
SURL="$(swift auth | awk -F = '/OS_STORAGE_URL/ {print $2}')"

作为共享用户,创建一个名为 shared 的共享容器,以只读模式使用适当的 ACL 与另一个用户共享

sharing.openrc
swift post --read-acl "*:${OUID}" shared

作为共享用户,创建并上传一个测试文件

touch void
swift upload shared void

作为另一个用户,列出 shared 容器中的文件

other.openrc
swift --os-storage-url="${SURL}" list shared

作为另一个用户,将 shared 容器下载到 /tmp 目录

cd /tmp
swift --os-storage-url="${SURL}" download shared

帐户 ACL

注意

帐户 ACL 当前不受 Keystone 身份验证支持

The X-Account-Access-Control 标头用于以特定于身份验证系统的格式指定帐户级别的 ACL。这些标头仅对帐户所有者(对于这些所有者 swift_owner 为 true)可见和可设置。帐户 ACL 的行为取决于身份验证系统。在 TempAuth 的情况下,如果经过身份验证的用户是 ACL 中列出的组的成员,则允许该用户访问该 ACL 的访问级别。

帐户 ACL 使用“V2”ACL 语法,这是一种具有名为“admin”、“read-write”和“read-only”的键的 JSON 字典。(请注意区分大小写。)X-Account-Access-Control 标头的一个示例值如下,其中 abc 是用户名

{"admin":["a","b"],"read-only":["c"]}

键可能缺失(如上例所示)。

生成 ACL 字符串的推荐方法如下

from swift.common.middleware.acl import format_acl
acl_data = { 'admin': ['alice'], 'read-write': ['bob', 'carol'] }
acl_string = format_acl(version=2, acl_dict=acl_data)

使用 format_acl() 方法将确保 JSON 以 ASCII 编码(例如,使用 ‘u1234’ 表示 Unicode)。虽然手动发送包含 X-Account-Access-Control 头部的 curl 命令是允许的,但由于人为错误的潜在风险,您应该谨慎操作。

在存储在 X-Account-Access-Control 中的 JSON 字典中,键具有以下含义

访问级别

描述

只读

这些身份可以读取帐户中的所有内容(特权头部除外)。具体来说,具有只读帐户访问权限的用户可以获取帐户中的容器列表,列出任何容器的内容,检索任何对象,并查看帐户、任何容器或任何对象的(非特权)头部。

读写

这些身份可以读取或写入(或创建)任何容器。具有读写帐户访问权限的用户可以创建新容器,设置任何非特权容器头部,覆盖对象,删除容器等。读写用户不能设置帐户头部(或对帐户执行任何 PUT/POST/DELETE 请求)。

admin(管理员)

这些身份具有“swift_owner”权限。具有管理员帐户访问权限的用户可以执行帐户所有者可以执行的任何操作,包括设置帐户头部和任何特权头部——从而授予其他用户只读、读写或管理员访问权限。

有关更多详细信息,请参阅 swift.common.middleware.tempauth。有关 ACL 格式的详细信息,请参阅 swift.common.middleware.acl