3.3. 使用 S3 API 访问 Ceph 对象网关
作为开发者,您必须配置对 Ceph 对象网关和安全令牌服务(STS)的访问权限,然后才能开始使用 Amazon S3 API。
3.3.1. 先决条件
- 一个正在运行的 Red Hat Ceph Storage 集群。
- 正在运行的 Ceph 对象网关.
- RESTful 客户端。
3.3.2. S3 身份验证
对 Ceph 对象网关的请求可以是经过身份验证的用户或未经身份验证的请求。Ceph 对象网关假定匿名用户发送了未经身份验证的请求。Ceph 对象网关支持 ACL。
对于大多数用例,客户端使用现有开源库,如 Amazon SDK 的 AmazonS3Client
用于 Java 和 Python Boto。使用开源库,只需传递访问密钥和密钥,库会为您构建请求标头和身份验证签名。但是,您可以创建请求并签署它们。
在向 Ceph 对象网关服务器发送前,在请求中包括访问密钥和基于 64 编码的消息身份验证代码(HMAC)的要求。Ceph 对象网关使用兼容 S3 的身份验证方法。
示例
HTTP/1.1 PUT /buckets/bucket/object.mpeg Host: cname.domain.com Date: Mon, 2 Jan 2012 00:01:01 +0000 Content-Encoding: mpeg Content-Length: 9999999 Authorization: AWS ACCESS_KEY:HASH_OF_HEADER_AND_SECRET
在上例中,将 ACCESS_KEY
替换为 access key ID 的值,后跟一个冒号(:
)。将 HASH_OF_HEADER_AND_SECRET
替换为一个规范标头字符串的哈希值,以及与访问密钥 ID 对应的 secret。
生成标头字符串和 secret 的哈希值
生成标头字符串和 secret 的哈希值:
- 获取标头字符串的值。
- 将请求标头字符串规范化为规范形式。
- 使用 SHA-1 哈希算法生成 HMAC。
-
将
hmac
结果编码为 base-64。
规范化标头
将标头规范化为规范形式:
-
获取
所有内容
标题。 -
删除除
content-type
和content-md5
外的所有content-
标头。 -
确保
content-
标头名称是小写。 -
以字典顺序对
content-
标题排序。 -
确保带有
Date
标头,并确保指定的日期使用 GMT 而不是偏移量。 -
获取以
x-amz-
开头的所有标题。 -
确保
x-amz-
标头都是小写。 -
以数字方式对
x-amz-
标头进行排序。 - 将同一字段名称的多个实例合并到一个字段中,并使用逗号分隔字段值。
- 使用单个空格替换标题值中的空格和换行符。
- 在冒号前后删除空格。
- 在每个标头后面添加一个新行。
- 将标头合并回请求标头。
将 HASH_OF_HEADER_AND_SECRET
替换为 base-64 编码的 HMAC 字符串。
其它资源
- 如需了解更多详细信息,请参阅 Amazon Simple Storage Service 文档中的签名和授权 REST Requests 部分。
3.3.3. 服务器侧加密(SSE)
Ceph 对象网关支持为 S3 应用编程接口(API)上传对象的服务器端加密。服务器端加密意味着 S3 客户端以未加密的形式通过 HTTP 发送数据,而 Ceph 对象网关以加密的形式将数据存储在 Red Hat Ceph Storage 集群中。
- 红帽不支持静态大型对象(SLO)或动态大对象(DLO)的 S3 对象加密。
-
目前,没有 Server-Side 加密(SSE)模式支持
CopyObject
。它目前正在开发 [BZ#2149450]。
若要使用加密,客户端请求需要通过 SSL 连接发送请求。除非 Ceph 对象网关使用 SSL,否则红帽不支持从客户端进行 S3 加密。但是,出于测试目的,管理员可以使用 ceph config set client.rgw
命令,在测试期间禁用 SSL,在运行时将 rgw_crypt_require_ssl
配置设置设置为 false
,然后重新启动 Ceph 对象网关实例。
在生产环境中,可能无法通过 SSL 发送加密的请求。在这种情况下,使用 HTTP 和服务器端加密发送请求。
有关如何使用服务器端加密配置 HTTP 的详情,请参考下面的附加资源部分。
S3 多部分使用服务器端加密上传现在在多站点中正确复制。在以前的版本中,此类对象的副本通过解密损坏,您可以使用 radosgw-admin bucket resync encrypted multipart --bucket-name BUCKET_NAME
命令来识别多部分上传。此命令扫描加密多部分对象的主要非复制副本。对于每个对象,任何识别对象的 LastModified
时间戳都会被 1ns
递增,以便对等区再次复制它。对于使用 SSE 的多站点部署,请在升级所有区域后针对每个区域中的每个存储桶运行这个命令。这样可确保使用 SSE 在多站点中正确复制 S3 多部分上传。
管理加密密钥有两个选项:
客户提供的键
在使用客户提供的密钥时,S3 客户端会传递加密密钥以及每个请求来读取或写入加密数据。客户负责管理这些密钥。客户必须记住用于加密每个对象的 Ceph 对象网关的关键是什么。
Ceph 对象网关根据 Amazon SSE-C 规范在 S3 API 中实施客户提供的关键行为。
由于客户处理密钥管理,并且 S3 客户端将密钥传递到 Ceph 对象网关,因此 Ceph 对象网关不需要特殊配置来支持这种加密模式。
密钥管理服务
在使用密钥管理服务时,安全密钥管理服务存储密钥,Ceph 对象网关则按需检索密钥,为数据加密或解密请求提供服务。
Ceph 对象网关根据 Amazon SSE-KMS 规范在 S3 API 中实施关键管理服务行为。
目前,唯一测试的关键管理实施是 HashiCorp Vault 和 OpenStack Barbican。但是,OpenStack Barbican 是一个技术预览,不支持在生产环境中使用。
3.3.4. S3 访问控制列表
Ceph 对象网关支持 S3 兼容访问控制列表(ACL)功能。ACL 是访问权限列表,可指定用户可以对存储桶或对象执行的操作。在应用到存储桶而不是应用到对象时,每个授权都有不同的意义:
权限 | Bucket | Object |
---|---|---|
| Grantee 可以列出存储桶中的对象。 | Grantee 可以读取对象。 |
| Grantee 可以编写或删除存储桶中的对象。 | 不适用 |
| Grantee 可以读取存储桶 ACL。 | Grantee 可以读取对象 ACL。 |
| Grantee 可以编写存储桶 ACL。 | Grantee 可以写入对象 ACL。 |
| Grantee 具有存储桶中对象的完整权限。 | Grantee 可以读取和写入对象 ACL。 |
3.3.5. 使用 S3 准备对 Ceph 对象网关的访问
在尝试访问网关服务器前,您必须在 Ceph 对象网关节点上遵循一些前提条件。
先决条件
- 安装 Ceph 对象网关软件.
- Ceph 对象网关节点的根级别访问权限.
流程
以
root
用户身份,在防火墙上打开端口8080
:[root@rgw ~]# firewall-cmd --zone=public --add-port=8080/tcp --permanent [root@rgw ~]# firewall-cmd --reload
在您要用于网关的 DNS 服务器中添加通配符,如 Object Gateway Configuration and Administration Guide 所述。
您还可以为本地 DNS 缓存设置网关节点。要做到这一点,请执行以下步骤:
以
root
用户身份,安装和设置dnsmasq
:[root@rgw ~]# yum install dnsmasq [root@rgw ~]# echo "address=/.FQDN_OF_GATEWAY_NODE/IP_OF_GATEWAY_NODE" | tee --append /etc/dnsmasq.conf [root@rgw ~]# systemctl start dnsmasq [root@rgw ~]# systemctl enable dnsmasq
将
IP_OF_GATEWAY_NODE
和FQDN_OF_GATEWAY_NODE
替换为网关节点的 IP 地址和 FQDN。作为
root
用户,停止 NetworkManager:[root@rgw ~]# systemctl stop NetworkManager [root@rgw ~]# systemctl disable NetworkManager
以
root
用户身份,将网关服务器的 IP 设置为名称服务器:[root@rgw ~]# echo "DNS1=IP_OF_GATEWAY_NODE" | tee --append /etc/sysconfig/network-scripts/ifcfg-eth0 [root@rgw ~]# echo "IP_OF_GATEWAY_NODE FQDN_OF_GATEWAY_NODE" | tee --append /etc/hosts [root@rgw ~]# systemctl restart network [root@rgw ~]# systemctl enable network [root@rgw ~]# systemctl restart dnsmasq
将
IP_OF_GATEWAY_NODE
和FQDN_OF_GATEWAY_NODE
替换为网关节点的 IP 地址和 FQDN。验证子域请求:
[user@rgw ~]$ ping mybucket.FQDN_OF_GATEWAY_NODE
将
FQDN_OF_GATEWAY_NODE
替换为网关节点的 FQDN。警告为本地 DNS 缓存设置网关服务器仅用于测试目的。执行此操作后,您无法访问外部网络。强烈建议您为 Red Hat Ceph Storage 集群和网关节点使用正确的 DNS 服务器。
-
如 Object Gateway Configuration and Administration Guide 所述,小心创建
radosgw
用于用于对S3
进行访问,并复制生成的access_key
和secret_key
。您需要这些密钥进行S3
访问和随后的 bucket 管理任务。
3.3.6. 使用 Ruby AWS S3 访问 Ceph 对象网关
您可以使用 Ruby 编程语言以及 aws-s3
gem 用于 S3
访问。在用于通过 Ruby AWS::S3
访问 Ceph 对象网关服务器的节点上执行下方所述的步骤。
先决条件
- Ceph 对象网关用户级访问权限.
- 访问 Ceph 对象网关的 root 级别访问节点。
- 互联网访问。
流程
安装
ruby
软件包:[root@dev ~]# yum install ruby
注意以上命令将安装
ruby
及其基本依赖项,如rubygems
和ruby-libs
。如果某种方式命令没有安装所有依赖项,请单独安装它们。安装
aws-s3
Ruby 软件包:[root@dev ~]# gem install aws-s3
创建项目目录:
[user@dev ~]$ mkdir ruby_aws_s3 [user@dev ~]$ cd ruby_aws_s3
创建连接文件:
[user@dev ~]$ vim conn.rb
将以下内容粘贴到
conn.rb
文件中:语法
#!/usr/bin/env ruby require 'aws/s3' require 'resolv-replace' AWS::S3::Base.establish_connection!( :server => 'FQDN_OF_GATEWAY_NODE', :port => '8080', :access_key_id => 'MY_ACCESS_KEY', :secret_access_key => 'MY_SECRET_KEY' )
将
FQDN_OF_GATEWAY_NODE
替换为 Ceph 对象网关节点的 FQDN。将MY_ACCESS_KEY
和MY_SECRET_KEY
替换为您在创建radosgw
用户来访问S3
时生成的access_key
和secret_key
,如 Red Hat Ceph Storage Object Gateway 配置和管理指南中所述。示例
#!/usr/bin/env ruby require 'aws/s3' require 'resolv-replace' AWS::S3::Base.establish_connection!( :server => 'testclient.englab.pnq.redhat.com', :port => '8080', :access_key_id => '98J4R9P22P5CDL65HKP8', :secret_access_key => '6C+jcaP0dp0+FZfrRNgyGA9EzRy25pURldwje049' )
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x conn.rb
运行该文件:
[user@dev ~]$ ./conn.rb | echo $?
如果您在文件中正确提供了值,命令的输出将是
0
。创建存储桶的新文件:
[user@dev ~]$ vim create_bucket.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' AWS::S3::Bucket.create('my-new-bucket1')
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x create_bucket.rb
运行该文件:
[user@dev ~]$ ./create_bucket.rb
如果命令的输出为
true
,这表示 bucketmy-new-bucket1
已创建成功。创建用于列出所拥有的存储桶的新文件:
[user@dev ~]$ vim list_owned_buckets.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' AWS::S3::Service.buckets.each do |bucket| puts "{bucket.name}\t{bucket.creation_date}" end
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x list_owned_buckets.rb
运行该文件:
[user@dev ~]$ ./list_owned_buckets.rb
输出应类似如下:
my-new-bucket1 2020-01-21 10:33:19 UTC
创建用于创建对象的新文件:
[user@dev ~]$ vim create_object.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' AWS::S3::S3Object.store( 'hello.txt', 'Hello World!', 'my-new-bucket1', :content_type => 'text/plain' )
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x create_object.rb
运行该文件:
[user@dev ~]$ ./create_object.rb
这将创建一个含有字符串
Hello World!
的文件hello.txt
。创建用于列出存储桶内容的新文件:
[user@dev ~]$ vim list_bucket_content.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' new_bucket = AWS::S3::Bucket.find('my-new-bucket1') new_bucket.each do |object| puts "{object.key}\t{object.about['content-length']}\t{object.about['last-modified']}" end
保存文件并退出编辑器。
使文件成为可执行文件。
[user@dev ~]$ chmod +x list_bucket_content.rb
运行该文件:
[user@dev ~]$ ./list_bucket_content.rb
输出将类似如下:
hello.txt 12 Fri, 22 Jan 2020 15:54:52 GMT
创建用于删除空存储桶的新文件:
[user@dev ~]$ vim del_empty_bucket.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' AWS::S3::Bucket.delete('my-new-bucket1')
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x del_empty_bucket.rb
运行该文件:
[user@dev ~]$ ./del_empty_bucket.rb | echo $?
如果删除了存储桶,命令会返回
0
作为输出。注意编辑
create_bucket.rb
文件,以创建空的 bucket,例如my-new-bucket4、
my-new-bucket5
。然后,在尝试删除空存储桶前相应地编辑上述del_empty_bucket.rb
文件。创建用于删除非空存储桶的新文件:
[user@dev ~]$ vim del_non_empty_bucket.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' AWS::S3::Bucket.delete('my-new-bucket1', :force => true)
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x del_non_empty_bucket.rb
运行该文件:
[user@dev ~]$ ./del_non_empty_bucket.rb | echo $?
如果删除了存储桶,命令会返回
0
作为输出。创建用于删除对象的新文件:
[user@dev ~]$ vim delete_object.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' AWS::S3::S3Object.delete('hello.txt', 'my-new-bucket1')
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x delete_object.rb
运行该文件:
[user@dev ~]$ ./delete_object.rb
这将删除对象
hello.txt
。
3.3.7. 使用 Ruby AWS SDK 访问 Ceph 对象网关
您可以使用 Ruby 编程语言以及 aws-sdk
gem 用于 S3
访问。在用于通过 Ruby AWS::SDK
访问 Ceph 对象网关服务器的节点上执行下方所述的步骤。
先决条件
- Ceph 对象网关用户级访问权限.
- 访问 Ceph 对象网关的 root 级别访问节点。
- 互联网访问。
流程
安装
ruby
软件包:[root@dev ~]# yum install ruby
注意以上命令将安装
ruby
及其基本依赖项,如rubygems
和ruby-libs
。如果某种方式命令没有安装所有依赖项,请单独安装它们。安装
aws-sdk
Ruby 软件包:[root@dev ~]# gem install aws-sdk
创建项目目录:
[user@dev ~]$ mkdir ruby_aws_sdk [user@dev ~]$ cd ruby_aws_sdk
创建连接文件:
[user@dev ~]$ vim conn.rb
将以下内容粘贴到
conn.rb
文件中:语法
#!/usr/bin/env ruby require 'aws-sdk' require 'resolv-replace' Aws.config.update( endpoint: 'http://FQDN_OF_GATEWAY_NODE:8080', access_key_id: 'MY_ACCESS_KEY', secret_access_key: 'MY_SECRET_KEY', force_path_style: true, region: 'us-east-1' )
将
FQDN_OF_GATEWAY_NODE
替换为 Ceph 对象网关节点的 FQDN。将MY_ACCESS_KEY
和MY_SECRET_KEY
替换为您在创建radosgw
用户来访问S3
时生成的access_key
和secret_key
,如 Red Hat Ceph Storage Object Gateway 配置和管理指南中所述。示例
#!/usr/bin/env ruby require 'aws-sdk' require 'resolv-replace' Aws.config.update( endpoint: 'http://testclient.englab.pnq.redhat.com:8080', access_key_id: '98J4R9P22P5CDL65HKP8', secret_access_key: '6C+jcaP0dp0+FZfrRNgyGA9EzRy25pURldwje049', force_path_style: true, region: 'us-east-1' )
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x conn.rb
运行该文件:
[user@dev ~]$ ./conn.rb | echo $?
如果您在文件中正确提供了值,命令的输出将是
0
。创建存储桶的新文件:
[user@dev ~]$ vim create_bucket.rb
将以下内容粘贴到文件中:
语法
#!/usr/bin/env ruby load 'conn.rb' s3_client = Aws::S3::Client.new s3_client.create_bucket(bucket: 'my-new-bucket2')
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x create_bucket.rb
运行该文件:
[user@dev ~]$ ./create_bucket.rb
如果命令的输出为
true
,这表示 bucketmy-new-bucket2
已创建成功。创建用于列出所拥有的存储桶的新文件:
[user@dev ~]$ vim list_owned_buckets.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' s3_client = Aws::S3::Client.new s3_client.list_buckets.buckets.each do |bucket| puts "{bucket.name}\t{bucket.creation_date}" end
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x list_owned_buckets.rb
运行该文件:
[user@dev ~]$ ./list_owned_buckets.rb
输出应类似如下:
my-new-bucket2 2020-01-21 10:33:19 UTC
创建用于创建对象的新文件:
[user@dev ~]$ vim create_object.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' s3_client = Aws::S3::Client.new s3_client.put_object( key: 'hello.txt', body: 'Hello World!', bucket: 'my-new-bucket2', content_type: 'text/plain' )
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x create_object.rb
运行该文件:
[user@dev ~]$ ./create_object.rb
这将创建一个含有字符串
Hello World!
的文件hello.txt
。创建用于列出存储桶内容的新文件:
[user@dev ~]$ vim list_bucket_content.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' s3_client = Aws::S3::Client.new s3_client.list_objects(bucket: 'my-new-bucket2').contents.each do |object| puts "{object.key}\t{object.size}" end
保存文件并退出编辑器。
使文件成为可执行文件。
[user@dev ~]$ chmod +x list_bucket_content.rb
运行该文件:
[user@dev ~]$ ./list_bucket_content.rb
输出将类似如下:
hello.txt 12 Fri, 22 Jan 2020 15:54:52 GMT
创建用于删除空存储桶的新文件:
[user@dev ~]$ vim del_empty_bucket.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' s3_client = Aws::S3::Client.new s3_client.delete_bucket(bucket: 'my-new-bucket2')
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x del_empty_bucket.rb
运行该文件:
[user@dev ~]$ ./del_empty_bucket.rb | echo $?
如果删除了存储桶,命令会返回
0
作为输出。注意编辑
create_bucket.rb
文件,以创建空的 bucket,例如my-new-bucket6
、my-new-bucket7
。然后,在尝试删除空存储桶前相应地编辑上述del_empty_bucket.rb
文件。创建用于删除非空存储桶的新文件:
[user@dev ~]$ vim del_non_empty_bucket.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' s3_client = Aws::S3::Client.new Aws::S3::Bucket.new('my-new-bucket2', client: s3_client).clear! s3_client.delete_bucket(bucket: 'my-new-bucket2')
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x del_non_empty_bucket.rb
运行该文件:
[user@dev ~]$ ./del_non_empty_bucket.rb | echo $?
如果删除了存储桶,命令会返回
0
作为输出。创建用于删除对象的新文件:
[user@dev ~]$ vim delete_object.rb
将以下内容粘贴到文件中:
#!/usr/bin/env ruby load 'conn.rb' s3_client = Aws::S3::Client.new s3_client.delete_object(key: 'hello.txt', bucket: 'my-new-bucket2')
保存文件并退出编辑器。
使文件可执行:
[user@dev ~]$ chmod +x delete_object.rb
运行该文件:
[user@dev ~]$ ./delete_object.rb
这将删除对象
hello.txt
。
3.3.8. 使用 PHP 访问 Ceph 对象网关
您可以使用 PHP 脚本进行 S3 访问。此流程提供一些示例 PHP 脚本来执行各种任务,如删除存储桶或对象。
以下给出的示例针对 php v5.4.16
和 aws-sdk v2.8.24
测试。不要使用最新版本的 aws-sdk
for php
,因为它需要没有包括在 RHEL 7
默认仓库中的 php >= 5.5+
.php 5.5
。如果要使用 php 5.5
,则必须启用 epel
和其他第三方存储库。另外,php 5.5
和最新版本的 aws-sdk
的配置选项也不同。
先决条件
- 根级访问开发工作站。
- 互联网访问。
流程
安装
php
软件包:[root@dev ~]# yum install php
-
下载适用于 PHP 的
aws-sdk
的 zip 存档并解压缩。 创建项目目录:
[user@dev ~]$ mkdir php_s3 [user@dev ~]$ cd php_s3
将提取的
aws
目录复制到项目目录中。例如:[user@dev ~]$ cp -r ~/Downloads/aws/ ~/php_s3/
创建连接文件:
[user@dev ~]$ vim conn.php
将以下内容粘贴到
conn.php
文件中:语法
<?php define('AWS_KEY', 'MY_ACCESS_KEY'); define('AWS_SECRET_KEY', 'MY_SECRET_KEY'); define('HOST', 'FQDN_OF_GATEWAY_NODE'); define('PORT', '8080'); // require the AWS SDK for php library require '/PATH_TO_AWS/aws-autoloader.php'; use Aws\S3\S3Client; // Establish connection with host using S3 Client client = S3Client::factory(array( 'base_url' => HOST, 'port' => PORT, 'key' => AWS_KEY, 'secret' => AWS_SECRET_KEY )); ?>
将
FQDN_OF_GATEWAY_NODE
替换为网关节点的 FQDN。将MY_ACCESS_KEY
和MY_SECRET_KEY
替换为创建radosgw
用户来访问S3
时生成的access_key
和secret_key
,如 Red Hat Ceph Storage Object Gateway 配置和管理指南 中所述。将PATH_TO_AWS
替换为您复制到php
项目目录的提取aws
目录的绝对路径。保存文件并退出编辑器。
运行该文件:
[user@dev ~]$ php -f conn.php | echo $?
如果您在文件中正确提供了值,命令的输出将是
0
。创建存储桶的新文件:
[user@dev ~]$ vim create_bucket.php
将以下内容粘贴到新文件中:
语法
<?php include 'conn.php'; client->createBucket(array('Bucket' => 'my-new-bucket3')); ?>
保存文件并退出编辑器。
运行该文件:
[user@dev ~]$ php -f create_bucket.php
创建用于列出所拥有的存储桶的新文件:
[user@dev ~]$ vim list_owned_buckets.php
将以下内容粘贴到文件中:
语法
<?php include 'conn.php'; blist = client->listBuckets(); echo "Buckets belonging to " . blist['Owner']['ID'] . ":\n"; foreach (blist['Buckets'] as b) { echo "{b['Name']}\t{b['CreationDate']}\n"; } ?>
保存文件并退出编辑器。
运行该文件:
[user@dev ~]$ php -f list_owned_buckets.php
输出应类似于如下:
my-new-bucket3 2020-01-21 10:33:19 UTC
首先创建名为
hello.txt
的源文件,以创建对象:[user@dev ~]$ echo "Hello World!" > hello.txt
创建新 php 文件:
[user@dev ~]$ vim create_object.php
将以下内容粘贴到文件中:
语法
<?php include 'conn.php'; key = 'hello.txt'; source_file = './hello.txt'; acl = 'private'; bucket = 'my-new-bucket3'; client->upload(bucket, key, fopen(source_file, 'r'), acl); ?>
保存文件并退出编辑器。
运行该文件:
[user@dev ~]$ php -f create_object.php
这将在 bucket
my-new-bucket3
中创建对象hello.txt
。创建用于列出存储桶内容的新文件:
[user@dev ~]$ vim list_bucket_content.php
将以下内容粘贴到文件中:
语法
<?php include 'conn.php'; o_iter = client->getIterator('ListObjects', array( 'Bucket' => 'my-new-bucket3' )); foreach (o_iter as o) { echo "{o['Key']}\t{o['Size']}\t{o['LastModified']}\n"; } ?>
保存文件并退出编辑器。
运行该文件:
[user@dev ~]$ php -f list_bucket_content.php
输出类似如下:
hello.txt 12 Fri, 22 Jan 2020 15:54:52 GMT
创建用于删除空存储桶的新文件:
[user@dev ~]$ vim del_empty_bucket.php
将以下内容粘贴到文件中:
语法
<?php include 'conn.php'; client->deleteBucket(array('Bucket' => 'my-new-bucket3')); ?>
保存文件并退出编辑器。
运行该文件:
[user@dev ~]$ php -f del_empty_bucket.php | echo $?
如果删除了存储桶,命令会返回
0
作为输出。注意编辑
create_bucket.php
文件,以创建空的 bucket,如my-new-bucket4、
my-new-bucket5
。然后,在尝试删除空存储桶前相应地编辑上述del_empty_bucket.php
文件。重要PHP 2 和
aws-sdk
的新版本不支持删除非空存储桶。创建用于删除对象的新文件:
[user@dev ~]$ vim delete_object.php
将以下内容粘贴到文件中:
语法
<?php include 'conn.php'; client->deleteObject(array( 'Bucket' => 'my-new-bucket3', 'Key' => 'hello.txt', )); ?>
保存文件并退出编辑器。
运行该文件:
[user@dev ~]$ php -f delete_object.php
这将删除对象
hello.txt
。
3.3.9. 安全令牌服务
Amazon Web Services 的安全令牌服务(STS)返回一组临时安全凭证来验证用户。Ceph 对象网关实施 STS 应用程序编程接口(API)的子集,为身份和访问管理(IAM)提供临时凭证。使用这些临时凭证,通过在 Ceph 对象网关中使用 STS 引擎来验证 S3 调用。您可以使用 IAM 策略限制临时凭证,该策略是传递给 STS API 的参数。
其它资源
- Amazon Web Services Secure Token Service 欢迎页面。
- 有关 STS Lite 和 Keystone 的详细信息,请参阅 Red Hat Ceph Storage Developer Guide 中的配置并使用 STS Lite。
- 如需了解有关 STS Lite 和 Keystone 的限制 的详细信息,请参阅 Red Hat Ceph Storage Developer Guide 中使用 STS Lite 的限制。
3.3.9.1. 安全令牌服务应用程序编程接口
Ceph 对象网关实施下列安全令牌服务(STS)应用程序编程接口(API):
AssumeRole
此 API 返回一组临时凭证,用于跨帐户访问。这些临时凭证都允许,附加了 AssumeRole API 的 Role 和策略的权限策略。RoleArn
和 RoleSessionName
请求参数是必需的,但其他请求参数是可选的。
RoleArn
- 描述
- 假定为 Amazon 资源名(ARN)的角色,长度为 20 到 2048 个字符。
- Type
- 字符串
- 必需
- 是
RoleSessionName
- 描述
-
识别要假定的角色会话名称。当不同的主体或不同的原因假设角色时,角色会话名称可以唯一标识一个会话。此参数的值的长度为 2 到 64 个字符。允许使用
=
、、、、@
和-
字符,但不允许有空格。 - Type
- 字符串
- 必需
- 是
policy
- 描述
- 以 JSON 格式的身份和访问管理策略(IAM),用于在内联会话中使用。此参数的值的长度为 1 到 2048 个字符。
- Type
- 字符串
- 必需
- 否
DurationSeconds
- 描述
-
会话持续时间(以秒为单位),最小值为
900
秒,最大值为43200
秒。默认值为3600
秒。 - Type
- 整数
- 必需
- 否
ExternalId
- 描述
- 假设另一个帐户的角色时,请提供一个唯一的外部标识符(如果可用)。这个参数的值的长度为 2 到 1224 个字符。
- Type
- 字符串
- 必需
- 否
SerialNumber
- 描述
- 用户从关联的多因素身份验证(MFA)设备识别号。参数的值可以是硬件设备或虚拟设备的序列号,长度为 9 到 256 个字符。
- Type
- 字符串
- 必需
- 否
TokenCode
- 描述
- 如果信任策略需要 MFA,则从多因素身份验证(MFA)设备生成的值。如果需要 MFA 设备,如果此参数的值为空或过期,则 AssumeRole 调用会返回 "access denied" 错误消息。这个参数的值的固定长度为 6 个字符。
- Type
- 字符串
- 必需
- 否
AssumeRoleWithWebIdentity
此 API 为应用进行身份验证的用户返回一组临时凭据,如 OpenID Connect 或 OAuth 2.0 身份提供程序。RoleArn
和 RoleSessionName
请求参数是必需的,但其他请求参数是可选的。
RoleArn
- 描述
- 假定为 Amazon 资源名(ARN)的角色,长度为 20 到 2048 个字符。
- 类型
- 字符串
- 必需
- 是
RoleSessionName
- 描述
-
识别要假定的角色会话名称。当不同的主体或不同的原因假设角色时,角色会话名称可以唯一标识一个会话。此参数的值的长度为 2 到 64 个字符。允许使用
=
、、、、
@
和-
字符,但不允许有空格。 - Type
- 字符串
- 必需
- 是
policy
- 描述
- 以 JSON 格式的身份和访问管理策略(IAM),用于在内联会话中使用。此参数的值的长度为 1 到 2048 个字符。
- Type
- 字符串
- 必需
- 否
DurationSeconds
- 描述
-
会话持续时间(以秒为单位),最小值为
900
秒,最大值为43200
秒。默认值为3600
秒。 - Type
- 整数
- 必需
- 否
ProviderId
- 描述
- 身份提供程序中域名的完全限定主机组件。此参数的值仅对 OAuth 2.0 访问令牌有效,长度为 4 到 2048 个字符。
- Type
- 字符串
- 必需
- 否
WebIdentityToken
- 描述
- 从身份提供程序提供的 OpenID Connect 身份令牌或 OAuth 2.0 访问令牌。此参数的值的长度为 4 到 2048 个字符。
- Type
- 字符串
- 必需
- 否
其它资源
- 如需了解更多详细信息,请参阅 Red Hat Ceph Storage 开发者指南中的 使用 安全令牌服务 API 部分的示例。
- Amazon Web Services Security Token Service,AssumeRole 操作。
- Amazon Web Services Security Token Service,AssumeRoleWithWebIdentity 操作。
3.3.9.2. 配置安全令牌服务
通过设置 rgw_sts_key
和 rgw_s3_auth_use_sts
选项,配置与 Ceph 对象网关搭配使用的安全令牌服务(STS)。
S3 和 STS API 共同存在于同一命名空间中,两者都可从 Ceph 对象网关中的同一端点访问。
先决条件
- 一个正在运行的 Red Hat Ceph Storage 集群。
- 正在运行的 Ceph 对象网关.
- Ceph 管理器节点的 root 级别访问。
流程
为 Ceph 对象网关客户端设置以下配置选项:
语法
ceph config set RGW_CLIENT_NAME rgw_sts_key STS_KEY ceph config set RGW_CLIENT_NAME rgw_s3_auth_use_sts true
rgw_sts_key
是用于加密或解密会话令牌的 STS 密钥,且正好为 16 十六进制字符。重要STS 密钥需要是字母数字。
示例
[root@mgr ~]# ceph config set client.rgw rgw_sts_key 7f8fd8dd4700mnop [root@mgr ~]# ceph config set client.rgw rgw_s3_auth_use_sts true
重新启动 Ceph 对象网关,使添加的密钥生效。
注意使用
ceph orch ps
命令的输出,在NAME
列下获取 SERVICE_TYPE。ID 信息。在存储集群中的单个节点上重启 Ceph 对象网关:
语法
systemctl restart ceph-CLUSTER_ID@SERVICE_TYPE.ID.service
示例
[root@host01 ~]# systemctl restart ceph-c4b34c6f-8365-11ba-dc31-529020a7702d@rgw.realm.zone.host01.gwasto.service
在存储集群的所有节点上重启 Ceph 对象网关:
语法
ceph orch restart SERVICE_TYPE
示例
[ceph: root@host01 /]# ceph orch restart rgw
其它资源
- 有关 STS API 的详情,请参阅 Red Hat Ceph Storage 开发者指南中的安全令牌服务应用程序接口 部分。
- 有关使用 Ceph 配置数据库的更多详情,请参阅 Red Hat Ceph Storage 配置指南中的 Ceph 配置的基础知识。
3.3.9.3. 为 OpenID Connect 供应商创建用户
要在 Ceph 对象网关和 OpenID Connect 供应商间建立信任,请创建一个用户实体和角色信任策略。
先决条件
- Ceph 对象网关节点的用户级访问权限。
流程
创建新 Ceph 用户:
语法
radosgw-admin --uid USER_NAME --display-name "DISPLAY_NAME" --access_key USER_NAME --secret SECRET user create
示例
[user@rgw ~]$ radosgw-admin --uid TESTER --display-name "TestUser" --access_key TESTER --secret test123 user create
配置 Ceph 用户功能:
语法
radosgw-admin caps add --uid="USER_NAME" --caps="oidc-provider=*"
示例
[user@rgw ~]$ radosgw-admin caps add --uid="TESTER" --caps="oidc-provider=*"
使用 Secure Token Service(STS)API 在角色信任策略中添加条件:
语法
"{\"Version\":\"2020-01-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Federated\":[\"arn:aws:iam:::oidc-provider/IDP_URL\"]},\"Action\":[\"sts:AssumeRoleWithWebIdentity\"],\"Condition\":{\"StringEquals\":{\"IDP_URL:app_id\":\"AUD_FIELD\"\}\}\}\]\}"
重要上述语法示例中的
app_id
必须与传入令牌的AUD_FIELD
字段匹配。
其它资源
- 请参阅 Amazon 网站上的 OpenID Connect 身份提供程序中包括 Root CA Thumbprint 的 Obtaining the OpenID Connect 身份提供程序。
- 有关 STS API 的详情,请参阅 Red Hat Ceph Storage 开发者指南中的安全令牌服务应用程序接口 部分。
- 如需了解更多详细信息,请参阅 Red Hat Ceph Storage 开发者指南中的 使用 安全令牌服务 API 部分的示例。
3.3.9.4. 获取 OpenID Connect 供应商的 thumbprint
要获得 OpenID Connect 供应商(IDP)配置文档。
先决条件
-
安装
openssl
和curl
软件包。
流程
从 IDP 的 URL 获取配置文档:
语法
curl -k -v \ -X GET \ -H "Content-Type: application/x-www-form-urlencoded" \ "IDP_URL:8000/CONTEXT/realms/REALM/.well-known/openid-configuration" \ | jq .
示例
[user@client ~]$ curl -k -v \ -X GET \ -H "Content-Type: application/x-www-form-urlencoded" \ "http://www.example.com:8000/auth/realms/quickstart/.well-known/openid-configuration" \ | jq .
获取 IDP 证书:
语法
curl -k -v \ -X GET \ -H "Content-Type: application/x-www-form-urlencoded" \ "IDP_URL/CONTEXT/realms/REALM/protocol/openid-connect/certs" \ | jq .
示例
[user@client ~]$ curl -k -v \ -X GET \ -H "Content-Type: application/x-www-form-urlencoded" \ "http://www.example.com/auth/realms/quickstart/protocol/openid-connect/certs" \ | jq .
-
复制上一命令中的"x5c"响应的结果,并将它粘贴到
certificate.crt
文件中。在结束时包含--BEGIN CERTIFICATE--
开始和--END CERTIFICATE--
。 获取证书指纹:
语法
openssl x509 -in CERT_FILE -fingerprint -noout
示例
[user@client ~]$ openssl x509 -in certificate.crt -fingerprint -noout SHA1 Fingerprint=F7:D7:B3:51:5D:D0:D3:19:DD:21:9A:43:A9:EA:72:7A:D6:06:52:87
- 从 SHA1 指纹中删除所有冒号,并将其用作在 IAM 请求中创建 IDP 实体的输入。
其它资源
- 请参阅 Amazon 网站上的 OpenID Connect 身份提供程序中包括 Root CA Thumbprint 的 Obtaining the OpenID Connect 身份提供程序。
- 有关 STS API 的详情,请参阅 Red Hat Ceph Storage 开发者指南中的安全令牌服务应用程序接口 部分。
- 如需了解更多详细信息,请参阅 Red Hat Ceph Storage 开发者指南中的 使用 安全令牌服务 API 部分的示例。
3.3.9.5. 在 Keystone 中配置和使用 STS Lite(技术预览)
同一命名空间中的 Amazon 安全令牌服务(STS)和 S3 API 共存。STS 选项可以和 Keystone 选项一起配置。
S3 和 STS API 都可以使用 Ceph 对象网关中的同一端点来访问。
先决条件
- Red Hat Ceph Storage 5.0 或更高版本。
- 正在运行的 Ceph 对象网关.
- 安装 Boto Python 模块,版本 3 或更高版本。
- Ceph 管理器节点的 root 级别访问。
- OpenStack 节点的用户级访问权限。
流程
为 Ceph 对象网关客户端设置以下配置选项:
语法
ceph config set RGW_CLIENT_NAME rgw_sts_key STS_KEY ceph config set RGW_CLIENT_NAME rgw_s3_auth_use_sts true
rgw_sts_key
是用于加密或解密会话令牌的 STS 密钥,且正好为 16 十六进制字符。重要STS 密钥需要是字母数字。
示例
[root@mgr ~]# ceph config set client.rgw rgw_sts_key 7f8fd8dd4700mnop [root@mgr ~]# ceph config set client.rgw rgw_s3_auth_use_sts true
在 OpenStack 节点上生成 EC2 凭据:
示例
[user@osp ~]$ openstack ec2 credentials create +------------+--------------------------------------------------------+ | Field | Value | +------------+--------------------------------------------------------+ | access | b924dfc87d454d15896691182fdeb0ef | | links | {u'self': u'http://192.168.0.15/identity/v3/users/ | | | 40a7140e424f493d8165abc652dc731c/credentials/ | | | OS-EC2/b924dfc87d454d15896691182fdeb0ef'} | | project_id | c703801dccaf4a0aaa39bec8c481e25a | | secret | 6a2142613c504c42a94ba2b82147dc28 | | trust_id | None | | user_id | 40a7140e424f493d8165abc652dc731c | +------------+--------------------------------------------------------+
使用生成的凭证,通过 GetSessionToken API 来备份一组临时安全凭证:
示例
import boto3 access_key = b924dfc87d454d15896691182fdeb0ef secret_key = 6a2142613c504c42a94ba2b82147dc28 client = boto3.client('sts', aws_access_key_id=access_key, aws_secret_access_key=secret_key, endpoint_url=https://www.example.com/rgw, region_name='', ) response = client.get_session_token( DurationSeconds=43200 )
获取临时凭证可用于发出 S3 调用:
示例
s3client = boto3.client('s3', aws_access_key_id = response['Credentials']['AccessKeyId'], aws_secret_access_key = response['Credentials']['SecretAccessKey'], aws_session_token = response['Credentials']['SessionToken'], endpoint_url=https://www.example.com/s3, region_name='') bucket = s3client.create_bucket(Bucket='my-new-shiny-bucket') response = s3client.list_buckets() for bucket in response["Buckets"]: print "{name}\t{created}".format( name = bucket['Name'], created = bucket['CreationDate'], )
创建新的 S3Access 角色并配置策略。
使用管理 CAPS 为用户分配:
语法
radosgw-admin caps add --uid="USER" --caps="roles=*"
示例
[root@mgr ~]# radosgw-admin caps add --uid="gwadmin" --caps="roles=*"
创建 S3Access 角色:
语法
radosgw-admin role create --role-name=ROLE_NAME --path=PATH --assume-role-policy-doc=TRUST_POLICY_DOC
示例
[root@mgr ~]# radosgw-admin role create --role-name=S3Access --path=/application_abc/component_xyz/ --assume-role-policy-doc=\{\"Version\":\"2012-10-17\",\"Statement\":\[\{\"Effect\":\"Allow\",\"Principal\":\{\"AWS\":\[\"arn:aws:iam:::user/TESTER\"\]\},\"Action\":\[\"sts:AssumeRole\"\]\}\]\}
将权限策略附加到 S3Access 角色:
语法
radosgw-admin role-policy put --role-name=ROLE_NAME --policy-name=POLICY_NAME --policy-doc=PERMISSION_POLICY_DOC
示例
[root@mgr ~]# radosgw-admin role-policy put --role-name=S3Access --policy-name=Policy --policy-doc=\{\"Version\":\"2012-10-17\",\"Statement\":\[\{\"Effect\":\"Allow\",\"Action\":\[\"s3:*\"\],\"Resource\":\"arn:aws:s3:::example_bucket\"\}\]\}
-
现在,另一个用户可以假定
gwadmin
用户的角色。例如,gwuser
用户可以假定gwadmin
用户权限。 记录假定用户的
access_key
和secret_key
值。示例
[root@mgr ~]# radosgw-admin user info --uid=gwuser | grep -A1 access_key
使用 AssumeRole API 调用,提供来自假定用户的
access_key
和secret_key
值:示例
import boto3 access_key = 11BS02LGFB6AL6H1ADMW secret_key = vzCEkuryfn060dfee4fgQPqFrncKEIkh3ZcdOANY client = boto3.client('sts', aws_access_key_id=access_key, aws_secret_access_key=secret_key, endpoint_url=https://www.example.com/rgw, region_name='', ) response = client.assume_role( RoleArn='arn:aws:iam:::role/application_abc/component_xyz/S3Access', RoleSessionName='Bob', DurationSeconds=3600 )
重要AssumeRole API 需要 S3Access 角色。
其它资源
- 有关安装 Boto Python 模块的更多信息,请参阅 Red Hat Ceph Storage 对象网关指南中的 Test S3 访问 部分。
- 如需更多信息,请参阅 Red Hat Ceph Storage Object Gateway 指南中的 创建用户 部分。
3.3.9.6. 围绕将 STS Lite 与 Keystone 搭配使用的限制(技术预览)
Keystone 的一个限制是它不支持安全令牌服务(STS)请求。请求中不包含另一个限制的有效负载哈希。要解决这两个限制,必须修改 Boto 身份验证代码。
先决条件
- 正在运行的 Red Hat Ceph Storage 集群,版本 5.0 或更高版本。
- 正在运行的 Ceph 对象网关.
- 安装 Boto Python 模块,版本 3 或更高版本。
流程
打开并编辑 Boto 的
auth.py
文件。将以下四行添加到代码块中:
class SigV4Auth(BaseSigner): """ Sign a request with Signature V4. """ REQUIRES_REGION = True def __init__(self, credentials, service_name, region_name): self.credentials = credentials # We initialize these value here so the unit tests can have # valid values. But these will get overriden in ``add_auth`` # later for real requests. self._region_name = region_name if service_name == 'sts': 1 self._service_name = 's3' 2 else: 3 self._service_name = service_name 4
将以下两行添加到代码块中:
def _modify_request_before_signing(self, request): if 'Authorization' in request.headers: del request.headers['Authorization'] self._set_necessary_date_headers(request) if self.credentials.token: if 'X-Amz-Security-Token' in request.headers: del request.headers['X-Amz-Security-Token'] request.headers['X-Amz-Security-Token'] = self.credentials.token if not request.context.get('payload_signing_enabled', True): if 'X-Amz-Content-SHA256' in request.headers: del request.headers['X-Amz-Content-SHA256'] request.headers['X-Amz-Content-SHA256'] = UNSIGNED_PAYLOAD 1 else: 2 request.headers['X-Amz-Content-SHA256'] = self.payload(request)
其它资源
- 有关安装 Boto Python 模块的更多信息,请参阅 Red Hat Ceph Storage 对象网关指南中的 Test S3 访问 部分。