开发人员指南

Red Hat Ceph Storage 4

为 Red Hat Ceph Storage 使用各种应用程序编程接口

摘要

本文档提供有关为 AMD64 和 Intel 64 架构上运行的红帽 Ceph 存储使用各种应用程序编程接口的说明。
红帽承诺替换我们的代码、文档和网页属性中存在问题的语言。我们从这四个术语开始: master、slave、blacklist 和 whitelist。这些更改将在即将发行的几个发行本中逐渐实施。详情请查看 CTO Chris Wright 信息

第 1 章 Ceph 对象网关管理 API

作为开发人员,您可以通过与 RESTful 应用编程接口(API)交互来管理 Ceph 对象网关。Ceph 对象网关在 RESTful API 中提供 radosgw-admin 命令的功能。您可以管理可与其他管理平台集成的用户、数据、配额和使用。

注意

红帽建议在配置 Ceph 对象网关时使用命令行界面。

管理 API 提供以下功能:

1.1. 先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • RESTful 客户端。

1.2. 管理操作

管理应用程序编程接口(API)请求将在以可配置的"管理员"资源入口点开头的 URI 上执行。管理 API 的授权会复制 S3 授权机制。有些操作要求用户具有特殊的管理功能。响应实体类型(XML 或 JSON)可以指定为请求中的"格式"选项,如果未指定,则默认为 JSON。

示例

PUT /admin/user?caps&format=json HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
Content-Type: text/plain
Authorization: AUTHORIZATION-TOKEN

usage=read

1.3. 管理身份验证请求

Amazon 的 S3 服务使用访问密钥和请求标头的哈希以及密钥来验证请求。它具有提供经过身份验证的请求(特别是大型上传)的优势,无需 SSL 开销。

S3 API 的大部分用例涉及使用开源 S3 客户端,如 Amazon SDK 中的 Java 或 Python Boto 中的 AmazonS3Client。这些库不支持 Ceph 对象网关管理 API。您可以子类并扩展这些库,以支持 Ceph 管理 API。或者,您可以创建唯一的网关客户端。

创建 execute() 方法

本节中的 CephAdminAPI 示例类演示了如何创建可获取请求参数、验证请求、调用 Ceph 管理 API 并接收响应的 execute() 方法。

CephAdminAPI 类示例不受支持或用于商业用途。仅用于说明目的。

调用 Ceph 对象网关

客户端代码 包含对 Ceph 对象网关的五个调用,用于演示 CRUD 操作:

  • 创建用户
  • 获取用户
  • 修改用户
  • 创建子用户
  • 删除用户

要使用这个示例,获取 httpcomponents-client-4.5.3 Apache HTTP 组件。您可以在此处下载它 然后解压缩 tar 文件,进入其 lib 目录,并将内容复制到 JAVA_HOME 目录的 /jre/lib/ext 目录或自定义类路径。

当您检查 CephAdminAPI 类示例时,请注意 execute() 方法采用 HTTP 方法、请求路径、可选子资源、null (如果未指定)以及参数映射。要使用子资源(例如 subuserkey )执行,您需要在 execute() 方法中将子资源指定为参数。

示例方法:

  1. 构建 URI。
  2. 构建 HTTP 标头字符串。
  3. 实例化 HTTP 请求,例如 PUTPOSTGETDELETE
  4. Date 标头添加到 HTTP 标头字符串和请求标头中。
  5. Authorization 标头添加到 HTTP 请求标头中。
  6. 实例化 HTTP 客户端并传递实例化 HTTP 请求。
  7. 发出请求.
  8. 返回响应。

构建标头字符串

构建标头字符串是涉及 Amazon S3 验证过程的部分。特别是,示例方法执行以下操作:

  1. 添加请求类型,如 PUTPOSTGETDELETE
  2. 添加日期.
  3. 添加 requestPath。

请求类型应当为大写,无前导或尾随空格。如果您不修剪空格,身份验证将失败。待定日期以 GMT 表示,验证将失败。

示例方法没有任何其他标头。Amazon S3 验证过程按词序对 x-amz 标头进行排序。因此,如果您要添加 x-amz 标头,请确定以词典方式添加它们。

构建标头字符串后,下一步是实例化 HTTP 请求并传递 URI。考试方法使用 PUT 创建用户和子用户,GET 用于获取用户,POST 用于修改用户,使用 DELETE 来删除用户。

实例化请求后,请在 Date 标头后面添加 Authorization 标头。Amazon 的 S3 身份验证使用标准 Authorization 标头,并具有以下结构:

Authorization: AWS ACCESS-KEY:_HASH-OF-HEADER-AND-SECRET_

CephAdminAPI 示例类具有 base64Sha1Hmac() 方法,它取 admin 用户的标头字符串和 secret 密钥,再将 SHA1 HMAC 返回为 base-64 编码字符串。每个 execute() 调用都会调用同一行代码来构建 Authorization 标头:

httpRequest.addHeader("Authorization", "AWS " + this.getAccessKey() + ":" + base64Sha1Hmac(headerString.toString(), this.getSecretKey()));

以下 CephAdminAPI 示例类要求您将 access key、secret key 和端点传递给构造器。类提供访问器方法来在运行时更改它们。

示例

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.ZoneId;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.Header;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.http.client.utils.URIBuilder;

import java.util.Base64;
import java.util.Base64.Encoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Mac;

import java.util.Map;
import java.util.Iterator;
import java.util.Set;
import java.util.Map.Entry;

public class CephAdminAPI {

	/*
	 * Each call must specify an access key, secret key, endpoint and format.
	 */
	String accessKey;
	String secretKey;
	String endpoint;
	String scheme = "http"; //http only.
	int port = 80;

	/*
	 * A constructor that takes an access key, secret key, endpoint and format.
	 */
	public CephAdminAPI(String accessKey, String secretKey, String endpoint){
		this.accessKey = accessKey;
		this.secretKey = secretKey;
		this.endpoint = endpoint;
	}

	/*
	 * Accessor methods for access key, secret key, endpoint and format.
	 */
	public String getEndpoint(){
		return this.endpoint;
	}

	public void setEndpoint(String endpoint){
		this.endpoint = endpoint;
	}

	public String getAccessKey(){
		return this.accessKey;
	}

	public void setAccessKey(String accessKey){
		this.accessKey = accessKey;
	}

	public String getSecretKey(){
		return this.secretKey;
	}

	public void setSecretKey(String secretKey){
		this.secretKey = secretKey;
	}

	/*
	 * Takes an HTTP Method, a resource and a map of arguments and
	 * returns a CloseableHTTPResponse.
	 */
	public CloseableHttpResponse execute(String HTTPMethod, String resource,
                                        String subresource, Map arguments) {

		String httpMethod = HTTPMethod;
		String requestPath = resource;
		StringBuffer request = new StringBuffer();
		StringBuffer headerString = new StringBuffer();
		HttpRequestBase httpRequest;
		CloseableHttpClient httpclient;
		URI uri;
		CloseableHttpResponse httpResponse = null;

		try {

			uri = new URIBuilder()
				.setScheme(this.scheme)
				.setHost(this.getEndpoint())
				.setPath(requestPath)
				.setPort(this.port)
				.build();


			if (subresource != null){
				uri = new URIBuilder(uri)
					.setCustomQuery(subresource)
					.build();
			}


			for (Iterator iter = arguments.entrySet().iterator();
			iter.hasNext();) {
				Entry entry = (Entry)iter.next();
				uri = new URIBuilder(uri)
					.setParameter(entry.getKey().toString(),
                                 entry.getValue().toString())
					.build();

			}

			request.append(uri);

			headerString.append(HTTPMethod.toUpperCase().trim() + "\n\n\n");

			OffsetDateTime dateTime = OffsetDateTime.now(ZoneId.of("GMT"));
			DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME;
			String date = dateTime.format(formatter);

			headerString.append(date + "\n");
			headerString.append(requestPath);

			if (HTTPMethod.equalsIgnoreCase("PUT")){
				httpRequest = new HttpPut(uri);
			} else if (HTTPMethod.equalsIgnoreCase("POST")){
				httpRequest = new HttpPost(uri);
			} else if (HTTPMethod.equalsIgnoreCase("GET")){
				httpRequest = new HttpGet(uri);
			} else if (HTTPMethod.equalsIgnoreCase("DELETE")){
				httpRequest = new HttpDelete(uri);
			} else {
				System.err.println("The HTTP Method must be PUT,
				POST, GET or DELETE.");
				throw new IOException();
			}

			httpRequest.addHeader("Date", date);
			httpRequest.addHeader("Authorization", "AWS " + this.getAccessKey()
			+ ":" + base64Sha1Hmac(headerString.toString(),
			this.getSecretKey()));

			httpclient = HttpClients.createDefault();
			httpResponse = httpclient.execute(httpRequest);

		} 	catch  (URISyntaxException e){
			System.err.println("The URI is not formatted properly.");
			e.printStackTrace();
		}  catch (IOException e){
			System.err.println("There was an error making the request.");
			e.printStackTrace();
		}
			return httpResponse;
	}

	/*
	 * Takes a uri and a secret key and returns a base64-encoded
	 * SHA-1 HMAC.
	 */
	public String base64Sha1Hmac(String uri, String secretKey) {
		try {

			byte[] keyBytes = secretKey.getBytes("UTF-8");
			SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");

			Mac mac = Mac.getInstance("HmacSHA1");
			mac.init(signingKey);

			byte[] rawHmac = mac.doFinal(uri.getBytes("UTF-8"));

			Encoder base64 = Base64.getEncoder();
			return base64.encodeToString(rawHmac);

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}

后续 CephAdminAPIClient 示例演示了如何实例化 CephAdminAPI 类,构建请求参数映射,并使用 execute() 方法创建、获取、更新和删除用户。

示例

import java.io.IOException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import java.util.*;


public class CephAdminAPIClient {

	public static void main (String[] args){

		CephAdminAPI adminApi = new CephAdminAPI ("FFC6ZQ6EMIF64194158N",
		                            "Xac39eCAhlTGcCAUreuwe1ZuH5oVQFa51lbEMVoT",
		                            "ceph-client");

		/*
		 * Create a user
		 */
		Map requestArgs = new HashMap();
		requestArgs.put("access", "usage=read, write; users=read, write");
		requestArgs.put("display-name", "New User");
		requestArgs.put("email", "new-user@email.com");
		requestArgs.put("format", "json");
		requestArgs.put("uid", "new-user");

		CloseableHttpResponse response =
			adminApi.execute("PUT", "/admin/user", null, requestArgs);

		System.out.println(response.getStatusLine());
		HttpEntity entity = response.getEntity();

		try {
			System.out.println("\nResponse Content is: "
				+ EntityUtils.toString(entity, "UTF-8") + "\n");
			response.close();
		} catch (IOException e){
			System.err.println ("Encountered an I/O exception.");
			e.printStackTrace();
		}

		/*
		 * Get a user
		 */
		requestArgs = new HashMap();
		requestArgs.put("format", "json");
		requestArgs.put("uid", "new-user");

		response = adminApi.execute("GET", "/admin/user", null, requestArgs);

		System.out.println(response.getStatusLine());
		entity = response.getEntity();

		try {
			System.out.println("\nResponse Content is: "
				+ EntityUtils.toString(entity, "UTF-8") + "\n");
			response.close();
		} catch (IOException e){
			System.err.println ("Encountered an I/O exception.");
			e.printStackTrace();
		}

		/*
		 * Modify a user
		 */
		requestArgs = new HashMap();
		requestArgs.put("display-name", "John Doe");
		requestArgs.put("email", "johndoe@email.com");
		requestArgs.put("format", "json");
		requestArgs.put("uid", "new-user");
		requestArgs.put("max-buckets", "100");

		response = adminApi.execute("POST", "/admin/user", null, requestArgs);

		System.out.println(response.getStatusLine());
		entity = response.getEntity();

		try {
			System.out.println("\nResponse Content is: "
				+ EntityUtils.toString(entity, "UTF-8") + "\n");
			response.close();
		} catch (IOException e){
			System.err.println ("Encountered an I/O exception.");
			e.printStackTrace();
		}


		/*
		 * Create a subuser
		 */
		requestArgs = new HashMap();
		requestArgs.put("format", "json");
		requestArgs.put("uid", "new-user");
		requestArgs.put("subuser", "foobar");

		response = adminApi.execute("PUT", "/admin/user", "subuser", requestArgs);
		System.out.println(response.getStatusLine());
		entity = response.getEntity();

		try {
			System.out.println("\nResponse Content is: "
				+ EntityUtils.toString(entity, "UTF-8") + "\n");
			response.close();
		} catch (IOException e){
			System.err.println ("Encountered an I/O exception.");
			e.printStackTrace();
		}


		/*
		 * Delete a user
		 */
		requestArgs = new HashMap();
		requestArgs.put("format", "json");
		requestArgs.put("uid", "new-user");

		response = adminApi.execute("DELETE", "/admin/user", null, requestArgs);
		System.out.println(response.getStatusLine());
		entity = response.getEntity();

		try {
			System.out.println("\nResponse Content is: "
				+ EntityUtils.toString(entity, "UTF-8") + "\n");
			response.close();
		} catch (IOException e){
			System.err.println ("Encountered an I/O exception.");
			e.printStackTrace();
		}
	}
}

其它资源

  • 如需了解更多详细信息,请参见《 红帽 Ceph 存储开发人员指南》 中的 S3 身份验证部分
  • 有关 Amazon S3 身份验证流程的更多说明,请参阅 Amazon Simple Storage Service 文档中的 签名和验证 REST 请求 部分。

1.4. 创建管理用户

重要

要从 Ceph 对象网关节点运行 radosgw-admin 命令,请确保该节点具有 admin 密钥。admin 密钥可以从任何 Ceph 监控节点复制。

先决条件

  • Ceph 对象网关节点的根级别访问权限.

流程

  1. 创建对象网关用户:

    语法

    radosgw-admin user create --uid="USER_NAME" --display-name="DISPLAY_NAME"

    示例

    [user@client ~]$ radosgw-admin user create --uid="admin-api-user" --display-name="Admin API User"

    radosgw-admin 命令行界面将返回用户。

    输出示例

    {
        "user_id": "admin-api-user",
        "display_name": "Admin API User",
        "email": "",
        "suspended": 0,
        "max_buckets": 1000,
        "auid": 0,
        "subusers": [],
        "keys": [
            {
                "user": "admin-api-user",
                "access_key": "NRWGT19TWMYOB1YDBV1Y",
                "secret_key": "gr1VEGIV7rxcP3xvXDFCo4UDwwl2YoNrmtRlIAty"
            }
        ],
        "swift_keys": [],
        "caps": [],
        "op_mask": "read, write, delete",
        "default_placement": "",
        "placement_tags": [],
        "bucket_quota": {
            "enabled": false,
            "max_size_kb": -1,
            "max_objects": -1
        },
        "user_quota": {
            "enabled": false,
            "max_size_kb": -1,
            "max_objects": -1
        },
        "temp_url_keys": []
    }

  2. 为您创建的用户分配管理功能:

    语法

    radosgw-admin caps add --uid="USER_NAME" --caps="users=*"

    示例

    [user@client ~]$ radosgw-admin caps add --uid=admin-api-user --caps="users=*"

    radosgw-admin 命令行界面将返回用户。"caps": 将具有您分配给用户的功能:

    输出示例

    {
        "user_id": "admin-api-user",
        "display_name": "Admin API User",
        "email": "",
        "suspended": 0,
        "max_buckets": 1000,
        "auid": 0,
        "subusers": [],
        "keys": [
            {
                "user": "admin-api-user",
                "access_key": "NRWGT19TWMYOB1YDBV1Y",
                "secret_key": "gr1VEGIV7rxcP3xvXDFCo4UDwwl2YoNrmtRlIAty"
            }
        ],
        "swift_keys": [],
        "caps": [
            {
                "type": "users",
                "perm": "*"
            }
        ],
        "op_mask": "read, write, delete",
        "default_placement": "",
        "placement_tags": [],
        "bucket_quota": {
            "enabled": false,
            "max_size_kb": -1,
            "max_objects": -1
        },
        "user_quota": {
            "enabled": false,
            "max_size_kb": -1,
            "max_objects": -1
        },
        "temp_url_keys": []
    }

    现在,您有一个具有管理权限的用户。

1.5. 获取用户信息

获取用户信息.

功能

users=read

语法

GET /admin/user?format=json HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME

表 1.1. 请求参数

名称描述类型示例必需

uid

请求信息的用户。

字符串

foo_user

表 1.2. 响应实体

名称描述类型父级

user

用于用户数据信息的容器。

Container

不适用

user_id

用户 ID。

字符串

user

display_name

用户的显示名称.

字符串

user

suspended

真(如果用户被暂停)。

布尔值

user

max_buckets

用户拥有的最大 bucket 数量。

整数

user

subusers

与此用户帐户关联的子用户。

Container

user

keys

与此用户帐户关联的 S3 密钥.

Container

user

swift_keys

与此用户帐户关联的 Swift 密钥.

Container

user

caps

用户功能.

Container

user

如果成功,响应中包含用户信息。

特殊错误响应

none.

1.6. 创建用户

创建新用户。默认情况下,S3 密钥对将自动创建并在响应中返回。如果只提供 access-keysecret-key 中的一个,则会自动生成省略的密钥。默认情况下,生成的密钥会添加到密钥环中,而不替换现有的密钥对。如果指定了 access-key 并引用了用户拥有的现有密钥,则会修改它。

功能

`users=write`

语法

PUT /admin/user?format=json HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME

表 1.3. 请求参数

名称描述类型示例必需

uid

要创建的用户 ID。

字符串

foo_user

display-name

要创建的用户的显示名称。

字符串

foo user

email

与用户关联的电子邮件地址。

字符串

foo@bar.com

key-type

要生成的密钥类型,选项为:swift、s3(默认)。

字符串

s3 [s3]

access-key

指定 access key。

字符串

ABCD0EF12GHIJ2K34LMN

secret-key

指定 secret 密钥。

字符串

0AbCDEFg1h2i34JklM5nop6QrSTUV+WxyzaBC7D8

user-caps

用户功能.

字符串

usage=read, write; users=read

generate-key

生成新密钥对并添加到现有密钥环中。

布尔值

true [True]

max-buckets

指定用户可以拥有的最大存储桶数量。

整数

500 [1000]

suspended

指定是否应该暂停该用户。

布尔值

False [False]

表 1.4. 响应实体

名称描述类型父级

user

用于用户数据信息的容器。

Container

不适用

user_id

用户 ID。

字符串

user

display_name

用户的显示名称.

字符串

user

suspended

真(如果用户被暂停)。

布尔值

user

max_buckets

用户拥有的最大 bucket 数量。

整数

user

subusers

与此用户帐户关联的子用户。

Container

user

keys

与此用户帐户关联的 S3 密钥.

Container

user

swift_keys

与此用户帐户关联的 Swift 密钥.

Container

user

caps

用户功能.

Container

user

如果成功,响应中包含用户信息。

表 1.5. 特殊错误响应

名称描述Code

UserExists

尝试创建现有用户。

409 冲突

InvalidAccessKey

指定了无效的访问密钥。

400 错误请求

InvalidKeyType

指定了无效的密钥类型。

400 错误请求

InvalidSecretKey

指定无效的 secret 密钥。

400 错误请求

InvalidKeyType

指定了无效的密钥类型。

400 错误请求

KeyExists

所提供的 access key 存在,并属于其他用户.

409 冲突

EmailExists

所提供的电子邮件地址存在。

409 冲突

InvalidCap

尝试授予无效的管理功能。

400 错误请求

其它资源

1.7. 修改用户

修改现有用户。

功能

`users=write`

语法

POST /admin/user?format=json HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME

表 1.6. 请求参数

名称描述类型示例必需

uid

要修改的用户 ID。

字符串

foo_user

display-name

要修改的用户的显示名称。

字符串

foo user

email

要与用户关联的电子邮件地址。

字符串

foo@bar.com

generate-key

生成新密钥对并添加到现有密钥环中。

布尔值

True [False]

access-key

指定 access key。

字符串

ABCD0EF12GHIJ2K34LMN

secret-key

指定 secret 密钥。

字符串

0AbCDEFg1h2i34JklM5nop6QrSTUV+WxyzaBC7D8

key-type

要生成的密钥类型,选项为:swift、s3(默认)。

字符串

s3

user-caps

用户功能.

字符串

usage=read, write; users=read

max-buckets

指定用户可以拥有的最大存储桶数量。

整数

500 [1000]

suspended

指定是否应该暂停该用户。

布尔值

False [False]

表 1.7. 响应实体

名称描述类型父级

user

用于用户数据信息的容器。

Container

不适用

user_id

用户 ID。

字符串

user

display_name

用户的显示名称.

字符串

user

suspended

真(如果用户被暂停)。

布尔值

user

max_buckets

用户拥有的最大 bucket 数量。

整数

user

subusers

与此用户帐户关联的子用户。

Container

user

keys

与此用户帐户关联的 S3 密钥.

Container

user

swift_keys

与此用户帐户关联的 Swift 密钥.

Container

user

caps

用户功能.

Container

user

如果成功,响应中包含用户信息。

表 1.8. 特殊错误响应

名称描述Code

InvalidAccessKey

指定了无效的访问密钥。

400 错误请求

InvalidKeyType

指定了无效的密钥类型。

400 错误请求

InvalidSecretKey

指定无效的 secret 密钥。

400 错误请求

KeyExists

所提供的 access key 存在,并属于其他用户.

409 冲突

EmailExists

所提供的电子邮件地址存在。

409 冲突

InvalidCap

尝试授予无效的管理功能。

400 错误请求

其它资源

1.8. 删除用户

删除现有用户。

功能

`users=write`

语法

DELETE /admin/user?format=json HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME

表 1.9. 请求参数

名称描述类型示例必需

uid

要删除的用户 ID。

字符串

foo_user

可以。

purge-data

指定之后,也会删除属于用户的 bucket 和对象。

布尔值

true

响应实体

none.

特殊错误响应

none.

其它资源

1.9. 创建子用户

创建一个新子用户,主要用于使用 Swift API 的客户端。

注:有效的请求需要 gen-subusersubuser。通常,为了让子用户有用,必须通过指定 access 来授予其权限。与用户创建一样,如果在没有 secret 的情况下指定 subuser,则会自动生成 secret 密钥。

功能

`users=write`

语法

PUT /admin/user?subuser&format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.10. 请求参数

名称描述类型示例必需

uid

要在其下创建子用户的用户 ID。

字符串

foo_user

subuser

指定要创建的子用户 ID。

字符串

sub_foo

是(或 gen-subuser

gen-subuser

指定要创建的子用户 ID。

字符串

sub_foo

是(或 subuser

secret-key

指定 secret 密钥。

字符串

0AbCDEFg1h2i34JklM5nop6QrSTUVWxyzaBC7D8

key-type

要生成的密钥类型,选项为:swift(默认),s3.

字符串

swift [swift]

access

为子用户设置访问权限,应为 read, write, readwrite, full 之一。

字符串

read

generate-secret

生成机密密钥。

布尔值

True [False]

表 1.11. 响应实体

名称描述类型父级

subusers

与用户帐户关联的子用户。

Container

不适用

id

子用户 ID.

字符串

subusers

permissions

对用户帐户的子用户访问权限.

字符串

subusers

如果成功,响应中包含子用户信息。

表 1.12. 特殊错误响应

名称描述Code

SubuserExists

存在指定的子用户。

409 冲突

InvalidKeyType

指定了无效的密钥类型。

400 错误请求

InvalidSecretKey

指定无效的 secret 密钥。

400 错误请求

InvalidAccess

指定无效的子用户访问权限。

400 错误请求

1.10. 修改子用户

修改现有的子用户。

功能

`users=write`

语法

POST /admin/user?subuser&format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.13. 请求参数

名称描述类型示例必需

uid

要修改子用户的用户 ID。

字符串

foo_user

subuser

要修改的子用户 ID。

字符串

sub_foo

generate-secret

为子用户生成新的机密密钥,替换现有的密钥。

布尔值

True [False]

secret

指定 secret 密钥。

字符串

0AbCDEFg1h2i34JklM5nop6QrSTUV+WxyzaBC7D8

key-type

要生成的密钥类型,选项为:swift(默认),s3.

字符串

swift [swift]

access

为子用户设置访问权限,应为 read, write, readwrite, full 之一。

字符串

read

表 1.14. 响应实体

名称描述类型父级

subusers

与用户帐户关联的子用户。

Container

不适用

id

子用户 ID.

字符串

subusers

permissions

对用户帐户的子用户访问权限.

字符串

subusers

如果成功,响应中包含子用户信息。

表 1.15. 特殊错误响应

名称描述Code

InvalidKeyType

指定了无效的密钥类型。

400 错误请求

InvalidSecretKey

指定无效的 secret 密钥。

400 错误请求

InvalidAccess

指定无效的子用户访问权限。

400 错误请求

1.11. 删除子用户

删除现有的子用户。

功能

`users=write`

语法

DELETE /admin/user?subuser&format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.16. 请求参数

名称描述类型示例必需

uid

要删除子用户的用户 ID。

字符串

foo_user

subuser

要删除的子用户 ID。

字符串

sub_foo

purge-keys

删除属于该子用户的密钥。

布尔值

true [True]

响应实体

none.

特殊错误响应

none.

1.12. 为用户添加功能

向指定用户添加管理功能。

功能

`users=write`

语法

PUT /admin/user?caps&format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.17. 请求参数

名称描述类型示例必需

uid

向其添加管理功能的用户 ID:

字符串

foo_user

user-caps

添加到用户的管理功能。

字符串

usage=read, write

表 1.18. 响应实体

名称描述类型父级

user

用于用户数据信息的容器。

Container

不适用

user_id

用户 ID。

字符串

user

caps

用户功能.

Container

user

如果成功,响应中包含用户的功能。

表 1.19. 特殊错误响应

名称描述Code

InvalidCap

尝试授予无效的管理功能。

400 错误请求

1.13. 删除用户的能力

从指定用户删除管理功能。

功能

`users=write`

语法

DELETE /admin/user?caps&format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.20. 请求参数

名称描述类型示例必需

uid

从中移除管理功能的用户 ID。

字符串

foo_user

user-caps

从用户中删除的管理功能。

字符串

usage=read, write

表 1.21. 响应实体

名称描述类型父级

user

用于用户数据信息的容器。

Container

不适用

user_id

用户 ID。

字符串

user

caps

用户功能.

Container

user

如果成功,响应中包含用户的功能。

表 1.22. 特殊错误响应

名称描述Code

InvalidCap

尝试删除无效的管理功能。

400 错误请求

NoSuchCap

用户没有指定的能力。

404 未找到

1.14. 创建密钥

创建新密钥。如果指定了 subuser,则默认创建的密钥将为 swift 类型。如果只提供了 access-keysecret-key 中的一个,则会自动生成提交的密钥,也就是说,如果只指定了 secret-key,则会自动生成 access-key。默认情况下,生成的密钥会添加到密钥环中,而不替换现有的密钥对。如果指定了 access-key 并引用了用户拥有的现有密钥,则会修改它。响应是一个容器,其中列出了与创建的密钥相同的所有密钥。

注意

在创建 swift 密钥时,指定选项 access-key 将无效。此外,每个用户或子用户只能保存一个 swift 密钥。

功能

`users=write`

语法

PUT /admin/user?key&format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.23. 请求参数

名称描述类型示例必需

uid

用于接收新密钥的用户 ID。

字符串

foo_user

subuser

用于接收新密钥的子用户 ID。

字符串

sub_foo

key-type

要生成的密钥类型,选项为:swift、s3(默认)。

字符串

s3 [s3]

access-key

指定 access 键。

字符串

AB01C2D3EF45G6H7IJ8K

secret-key

指定 secret 密钥。

字符串

0ab/CdeFGhij1klmnopqRSTUv1WxyZabcDEFgHij

generate-key

生成新密钥对并添加到现有密钥环中。

布尔值

true [True]

表 1.24. 响应实体

名称描述类型父级

keys

与此用户帐户关联的类型密钥。

Container

不适用

user

与密钥关联的用户帐户。

字符串

keys

access-key

访问密钥。

字符串

keys

secret-key

secret 密钥

字符串

keys

表 1.25. 特殊错误响应

名称描述Code

InvalidAccessKey

指定了无效的访问密钥。

400 错误请求

InvalidKeyType

指定了无效的密钥类型。

400 错误请求

InvalidSecretKey

指定无效的 secret 密钥。

400 错误请求

InvalidKeyType

指定了无效的密钥类型。

400 错误请求

KeyExists

所提供的 access key 存在,并属于其他用户.

409 冲突

1.15. 删除密钥

删除现有的密钥。

功能

`users=write`

语法

DELETE /admin/user?key&format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.26. 请求参数

名称描述类型示例必需

access-key

属于 S3 密钥对的 S3 访问密钥,用于移除。

字符串

AB01C2D3EF45G6H7IJ8K

uid

从中移除密钥的用户。

字符串

foo_user

subuser

从中移除密钥的子用户。

字符串

sub_foo

key-type

要删除的密钥类型,选项为:swift、s3。注意:需要删除 swift 密钥。

字符串

swift

特殊错误响应

none.

响应实体

none.

1.16. bucket 通知

作为存储管理员,您可以使用这些 API 为存储桶通知机制提供配置和控制接口。API 主题是包含特定端点定义的命名对象。bucket 通知将主题与特定存储桶相关联.S3 bucket operations 部分提供有关 bucket 通知的更多详情。

注意

在所有主题操作中,参数都是 URL 编码的,并使用 application/x-www-form-urlencoded 内容类型在消息正文中发送。

注意

需要重新创建与该主题关联的任何存储桶通知,以使主题更新生效。

1.16.1. 先决条件

  • 在 Ceph 对象网关上创建 bucket 通知。

1.16.2. 创建主题

您可以在创建存储桶通知前创建主题。主题是一个简单通知服务(SNS)实体和所有主题操作,即 createdeletelistget 是 SNS 操作。该主题需要具有在创建存储桶通知时使用的端点参数。请求成功后,响应中包含 Amazon 资源名称(ARN)主题,稍后可用于在 bucket 通知请求中引用此主题。

注意

topic_arn 提供存储桶通知配置,并在创建主题后生成。

先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • 根级别访问权限.
  • 安装 Ceph 对象网关.
  • 用户 access key 和 secret key。
  • 端点参数.

流程

  1. 使用以下请求格式创建一个主题:

    语法

    POST
    Action=CreateTopic
    &Name=TOPIC_NAME
    [&Attributes.entry.1.key=amqp-exchange&Attributes.entry.1.value=EXCHANGE]
    [&Attributes.entry.2.key=amqp-ack-level&Attributes.entry.2.value=none|broker|routable]
    [&Attributes.entry.3.key=verify-ssl&Attributes.entry.3.value=true|false]
    [&Attributes.entry.4.key=kafka-ack-level&Attributes.entry.4.value=none|broker]
    [&Attributes.entry.5.key=use-ssl&Attributes.entry.5.value=true|false]
    [&Attributes.entry.6.key=ca-location&Attributes.entry.6.value=FILE_PATH]
    [&Attributes.entry.7.key=OpaqueData&Attributes.entry.7.value=OPAQUE_DATA]
    [&Attributes.entry.8.key=push-endpoint&Attributes.entry.8.value=ENDPOINT]

    以下是请求参数:

    • Endpoint: 要发送通知的端点的 URL。
    • OpaqueData: 不透明数据在主题配置中设置,并添加到该主题触发的所有通知中。
    • HTTP 端点:

      • URL: HTTP[s]://FQDN[: PORT ]
      • port defaults to: 相应地将 80/443 用于 HTTP[S]。
      • verify-ssl: 表示服务器证书是否由客户端验证。默认情况下,它是 true
    • AMQP0.9.1 端点:

      • URL: AMQP://[USER : PASSWORD @] FQDN [: PORT][/VHOST].
      • 用户和密码默认为: guestguest
      • 用户和密码只能通过 HTTPS 提供。否则,主题创建请求将被拒绝。
      • port defaults to: 5672.
      • vhost 默认值为:"/"
      • amqp-exchange:交换必须存在,并且能够基于主题路由消息。这是 AMQP0.9.1 的必要参数。指向同一端点的不同主题必须使用相同的交换。
      • amqp-ack-level: 无需结束确认,因为消息可能会在代理中保留,然后再传输到其最终目标位置。有三个确认方法:

        • none: 如果发送到代理,消息被视为 delivered
        • broker: 如果代理确认,则默认将该消息视为 delivered
        • routable: 如果代理可以路由到消费者的 : 消息被视为 delivered

          注意

          特定参数的键和值不必驻留在同一行或任何特定顺序中,但必须使用相同的索引。属性索引不需要从任何特定值连续或启动。

          注意

          topic-name 用于 AMQP 主题。

    • Kafka 端点:

      • URL: Kafka://[USER: PASSWORD @] FQDN[: PORT].
      • 如果 use-ssl 默认设置为 false。如果 use-ssl 设置为 true,则会使用安全连接来连接代理。
      • 如果提供了 ca-location,并使用了安全连接,则会使用指定的 CA 而不是默认 CA 来验证代理。
      • 用户和密码只能通过 HTTP[S] 提供。如果没有,则主题创建请求将被拒绝。
      • 用户和密码只能与 use-ssl 一同提供,如果没有,则与代理的连接会失败。
      • port defaults to: 9092.
      • kafka-ack-level: 不要求结束确认,因为消息可能会在代理中保留,然后再传送到最终目的地。有两种确认方法:

        • none: 如果发送到代理,消息被视为 delivered
        • broker: 默认情况下,代理确认该消息将被视为 delivered
  2. 使用以下格式创建响应:

    语法

    <CreateTopicResponse xmlns="https://sns.amazonaws.com/doc/2010-03-31/">
        <CreateTopicResult>
            <TopicArn></TopicArn>
        </CreateTopicResult>
        <ResponseMetadata>
            <RequestId></RequestId>
        </ResponseMetadata>
    </CreateTopicResponse>

    注意

    响应中的 Amazon 资源名称(ARN)主题将具有以下格式: arn:aws:sns:<_ZONE_GROUP_>:<_TENANT_>:<_TOPIC_>

    以下是 AMQP0.9.1 端点的示例:

    语法

    "client.create_topic(Name='my-topic' , Attributes={'push-endpoint': 'amqp://127.0.0.1:5672', 'amqp-exchange': 'ex1', 'amqp-ack-level': 'broker'})"

1.16.3. 获取主题信息

返回有关特定主题的信息。如果提供,这可以包括端点信息。

先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • 根级别访问权限.
  • 安装 Ceph 对象网关.
  • 用户 access key 和 secret key。
  • 端点参数.

流程

  1. 使用以下请求格式获取主题信息:

    语法

    POST
    Action=GetTopic
    &TopicArn=TOPIC_ARN

    以下是响应格式的示例:

    <GetTopicResponse>
      <GetTopicRersult>
        <Topic>
          <User>
          </User>
          <Name>
          </Name>
          <EndPoint>
            <EndpointAddress>
            </EndpointAddress>
            <EndpointArgs>
            </EndpointArgs>
            <EndpointTopic>
            </EndpointTopic>
          </EndPoint>
          <TopicArn>
          </TopicArn>
          <OpaqueData>
          </OpaqueData>
        </Topic>
      </GetTopicResult>
      <ResponseMetadata>
        <RequestId>
        </RequestId>
      </ResponseMetadata>
    </GetTopicResponse>

    这些标签及其定义:

    • User: 创建该主题的用户的名称。
    • Name: 主题的名称。
    • EndpointAddress:端点 URL。如果端点 URL 包含用户和密码信息,则必须通过 HTTPS 发出请求。否则,主题获取请求将被拒绝。
    • EndPointArgs:端点参数。
    • EndpointTopic: 将发送到端点的主题名称可能与上述主题名称不同。
    • TopicArn:主题 ARN.

1.16.4. 列出主题

列出用户定义的主题。

先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • 根级别访问权限.
  • 安装 Ceph 对象网关.
  • 用户 access key 和 secret key。
  • 端点参数.

流程

  1. 使用以下请求格式列出主题信息:

    POST
    Action=ListTopics

    以下是响应格式的示例:

    <ListTopicdResponse xmlns="https://sns.amazonaws.com/doc/2020-03-31/">
      <ListTopicsRersult>
        <Topics>
          <member>
            <User>
            </User>
            <Name>
            </Name>
            <EndPoint>
              <EndpointAddress>
              </EndpointAddress>
              <EndpointArgs>
              </EndpointArgs>
              <EndpointTopic>
              </EndpointTopic>
            </EndPoint>
            <TopicArn>
            </TopicArn>
            <OpaqueData>
            </OpaqueData>
          </member>
        </Topics>
      </ListTopicsResult>
      <ResponseMetadata>
        <RequestId>
        </RequestId>
      </ResponseMetadata>
    </ListTopicsResponse>
    注意

    如果端点 URL 包含用户和密码信息,则在任一主题中,必须通过 HTTPS 发出请求。如果没有,主题列表请求将被拒绝。

1.16.5. 删除主题

删除已删除的主题结果时无操作,而不是失败。

先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • 根级别访问权限.
  • 安装 Ceph 对象网关.
  • 用户 access key 和 secret key。
  • 端点参数.

流程

  1. 使用以下请求格式删除主题:

    语法

    POST
    Action=DeleteTopic
    &TopicArn=TOPIC_ARN

    以下是响应格式的示例:

    <DeleteTopicResponse xmlns="https://sns.amazonaws.com/doc/2020-03-31/">
      <ResponseMetadata>
        <RequestId>
        </RequestId>
      </ResponseMetadata>
    </DeleteTopicResponse>

1.16.6. 事件记录

事件包含 Ceph 对象网关所执行的操作的信息,并作为载荷通过所选端点发送,如 HTTP、HTTPS、Kafka 或 AMQ0.9.1。事件记录采用 JSON 格式。

示例

{"Records":[
    {
        "eventVersion":"2.1",
        "eventSource":"ceph:s3",
        "awsRegion":"us-east-1",
        "eventTime":"2019-11-22T13:47:35.124724Z",
        "eventName":"s3:ObjectCreated:Put",
        "userIdentity":{
            "principalId":"tester"
        },
        "requestParameters":{
            "sourceIPAddress":""
        },
        "responseElements":{
            "x-amz-request-id":"503a4c37-85eb-47cd-8681-2817e80b4281.5330.903595",
            "x-amz-id-2":"14d2-zone1-zonegroup1"
        },
        "s3":{
            "s3SchemaVersion":"1.0",
            "configurationId":"mynotif1",
            "bucket":{
                "name":"mybucket1",
                "ownerIdentity":{
                    "principalId":"tester"
                },
                "arn":"arn:aws:s3:us-east-1::mybucket1",
                "id":"503a4c37-85eb-47cd-8681-2817e80b4281.5332.38"
            },
            "object":{
                "key":"myimage1.jpg",
                "size":"1024",
                "eTag":"37b51d194a7513e45b56f6524f2d51f2",
                "versionId":"",
                "sequencer": "F7E6D75DC742D108",
                "metadata":[],
                "tags":[]
            }
        },
        "eventId":"",
        "opaqueData":"me@example.com"
    }
]}

这些是事件记录键及其定义:

  • awsRegion:Zonegroup.
  • eventTime: 表示何时触发事件的时间戳。
  • eventName: 事件的类型。
  • userIdentity.principalId:触发事件的用户的身份。
  • requestParameters.sourceIPAddress:触发该事件的客户端的 IP 地址。不支持此字段。
  • responseElements.x-amz-request-id: 触发事件的请求 ID。
  • responseElements.x_amz_id_2:触发该事件的 Ceph 对象网关的身份。身份格式为 RGWID-ZONE-ZONEGROUP
  • s3.configurationId: 创建事件的通知 ID。
  • s3.bucket.name:存储桶的名称。
  • s3.bucket.ownerIdentity.principalId:存储桶的所有者。
  • s3.bucket.arn: bucket 的 Amazon 资源名称(ARN)
  • s3.bucket.id:存储桶的身份。
  • s3.object.key: 对象密钥。
  • s3.object.size: 对象的大小。
  • s3.object.eTag: 对象 etag。
  • s3.object.version:版本控制 bucket 中的对象版本。
  • s3.object.sequencer: 以十六进制格式表示每个对象更改的单调递增标识符。
  • s3.object.metadata: 发送为 x-amz-meta 的对象上设置的任何元数据。
  • s3.object.tags: 对象上设置的任何标签。
  • s3.eventId:事件的唯一身份。
  • s3.opaqueData: 不透明数据在主题配置中设置,并添加到该主题触发的所有通知中。

其它资源

  • 如需更多信息,请参阅 事件消息结构
  • 如需更多信息,请参阅红帽 Ceph 存储开发人员指南中 的支持 事件类型 部分。

1.16.7. 支持的事件类型

支持以下事件类型:

  • s3:ObjectCreated:*
  • s3:ObjectCreated:Put
  • s3:ObjectCreated:Post
  • s3:ObjectCreated:Copy
  • s3:ObjectCreated:CompleteMultipartUpload
  • s3:ObjectRemoved:*
  • s3:ObjectRemoved:Delete
  • s3:ObjectRemoved:DeleteMarkerCreated

1.16.8. 其它资源

1.17. 获取存储桶信息

获取有关现有存储桶子集的信息。如果指定了 uid 没有 bucket,则会返回属于该用户的所有存储桶。如果只指定了 bucket,则会检索该特定存储桶的信息。

功能

`buckets=read`

语法

GET /admin/bucket?format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.27. 请求参数

名称描述类型示例必需

bucket

用于返回信息的 bucket。

字符串

foo_bucket

uid

要检索存储桶信息的用户.

字符串

foo_user

stats

返回 bucket 统计信息.

布尔值

True [False]

表 1.28. 响应实体

名称描述类型父级

stats

每存储桶信息.

Container

不适用

buckets

包含一个或多个 bucket 容器的列表。

Container

bucket

用于单个 bucket 信息的容器.

Container

buckets

name

bucket 的名称。

字符串

bucket

pool

bucket 存储在的池。

字符串

bucket

id

唯一的 bucket ID。

字符串

bucket

marker

内部 bucket 标签.

字符串

bucket

owner

bucket 所有者的用户 ID。

字符串

bucket

usage

存储使用信息.

Container

bucket

index

如果成功,请求将返回一个包含所需存储桶信息的 bucket 容器。

表 1.29. 特殊错误响应

名称描述Code

IndexRepairFailed

bucket 索引修复失败。

409 冲突

1.18. 检查存储桶索引

检查现有存储桶的索引。

注意

要使用 check-objects 检查多部分对象记帐,fix 必须设为 True。

功能

buckets=write

语法

GET /admin/bucket?index&format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.30. 请求参数

名称描述类型示例必需

bucket

用于返回信息的 bucket。

字符串

foo_bucket

check-objects

检查多部分对象记帐。

布尔值

True [False]

fix

另外,在检查时修复存储桶索引。

布尔值

False [False]

表 1.31. 响应实体

名称描述类型

index

bucket 索引的状态.

字符串

表 1.32. 特殊错误响应

名称描述Code

IndexRepairFailed

bucket 索引修复失败。

409 冲突

1.19. 删除存储桶

删除现有存储桶.

功能

`buckets=write`

语法

DELETE /admin/bucket?format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.33. 请求参数

名称描述类型示例必需

bucket

要删除的 bucket。

字符串

foo_bucket

purge-objects

删除之前删除存储桶对象。

布尔值

True [False]

响应实体

none.

表 1.34. 特殊错误响应

名称描述Code

BucketNotEmpty

尝试删除非空存储桶。

409 冲突

ObjectRemovalFailed

无法删除对象。

409 冲突

1.22. 获取存储桶或对象策略

阅读对象或存储桶的策略。

功能

`buckets=read`

语法

GET /admin/bucket?policy&format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.40. 请求参数

名称描述类型示例必需

bucket

要从中读取策略的 bucket。

字符串

foo_bucket

object

从中读取策略的对象。

字符串

foo.txt

表 1.41. 响应实体

名称描述类型父级

policy

访问控制策略.

Container

不适用

如果成功,则返回对象或存储桶策略

表 1.42. 特殊错误响应

名称描述Code

IncompleteBody

未为存储桶策略请求或存储桶指定存储桶,并且对象没有为对象策略请求指定。

400 错误请求

1.23. 删除对象

删除现有对象。

注意

不要求所有者不暂停。

功能

`buckets=write`

语法

DELETE /admin/bucket?object&format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.43. 请求参数

名称描述类型示例必需

bucket

包含要删除的对象的 bucket。

字符串

foo_bucket

object

要移除的对象。

字符串

foo.txt

响应实体

none.

表 1.44. 特殊错误响应

名称描述Code

NoSuchObject

指定的对象不存在。

404 未找到

ObjectRemovalFailed

无法删除对象。

409 冲突

1.24. 配额

管理运营 API 允许您在由用户拥有的 bucket 上设置用户和配额。配额包括 bucket 中对象的最大数量,以及最大存储大小(以 MB 为单位)。

要查看配额,用户必须具有 users=read 功能。要设置、修改或禁用配额,用户必须具有 users=write 功能。

配额的有效参数包括:

  • bucket: bucket 选项允许您为用户拥有的存储桶指定配额。
  • 最大对象: max-objects 设置允许您指定对象的最大数量。负值将禁用此设置。
  • 最大大小: max-size 选项允许您为最大字节数指定配额。负值将禁用此设置。
  • 配额范围: quota-scope 选项设置配额的范围。选项为 bucketuser

1.25. 获取用户配额

要获得配额,用户必须设置有 read 权限的 users 功能。

语法

GET /admin/user?quota&uid=UID&quota-type=user

1.26. 设置用户配额

要设置配额,用户必须设置有 write 权限的 users 功能。

语法

PUT /admin/user?quota&uid=UID&quota-type=user

内容必须包含配额设置的 JSON 表示,如对应的读取操作中编码。

1.27. 获取存储桶配额

获取有关现有存储桶子集的信息。如果指定了 uid 没有 bucket,则会返回属于该用户的所有存储桶。如果只指定了 bucket,则会检索该特定存储桶的信息。

功能

`buckets=read`

语法

GET /admin/bucket?format=json HTTP/1.1
Host FULLY_QUALIFIED_DOMAIN_NAME

表 1.45. 请求参数

名称描述类型示例必需

bucket

用于返回信息的 bucket。

字符串

foo_bucket

uid

要检索存储桶信息的用户.

字符串

foo_user

stats

返回 bucket 统计信息.

布尔值

True [False]

表 1.46. 响应实体

名称描述类型父级

stats

每存储桶信息.

Container

不适用

buckets

包含一个或多个 bucket 容器的列表。

Container

bucket

用于单个 bucket 信息的容器.

Container

buckets

name

bucket 的名称。

字符串

bucket

pool

bucket 存储在的池。

字符串

bucket

id

唯一的 bucket ID。

字符串

bucket

marker

内部 bucket 标签.

字符串

bucket

owner

bucket 所有者的用户 ID。

字符串

bucket

usage

存储使用信息.

Container

bucket

index

如果成功,请求将返回一个包含所需存储桶信息的 bucket 容器。

表 1.47. 特殊错误响应

名称描述Code

IndexRepairFailed

bucket 索引修复失败。

409 冲突

1.28. 设置存储桶配额

要设置配额,用户必须设置有 write 权限的 users 功能。

语法

PUT /admin/user?quota&uid=UID&quota-type=bucket

内容必须包含配额设置的 JSON 表示,如对应的读取操作中编码。

1.29. 获取使用情况信息

请求带宽使用信息.

功能

`usage=read`

语法

GET /admin/usage?format=json HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME

表 1.48. 请求参数

名称描述类型必需

uid

请求信息的用户。

字符串.

start

指定所请求数据的开始时间的日期和(可选)时间。例如, 2012-09-25 16:00:00

字符串

end

指定请求数据的结束时间(非包含)的日期和(可选)时间。例如, 2012-09-25 16:00:00

字符串

show-entries

指定是否应返回数据条目。

布尔值

show-summary

指定是否应返回数据摘要。

布尔值

表 1.49. 响应实体

名称描述类型

usage

用于使用信息的容器。

Container

entries

用于用法条目信息的容器。

Container

user

用于用户数据信息的容器。

Container

owner

拥有存储桶的用户的名称。

字符串

bucket

bucket 名称。

字符串

time

指定数据的时间下限(舍入到第一个相关小时的开头)。

字符串

epoch

1/1/1970 起指定的时间(以秒为单位)。

字符串

categories

适用于 stats 类别的容器。

Container

entry

stats 条目的容器。

Container

category

提供统计数据的请求类别名称。

字符串

bytes_sent

Ceph 对象网关发送的字节数。

整数

bytes_received

Ceph 对象网关收到的字节数。

整数

ops

操作数量.

整数

successful_ops

成功操作的数量.

整数

summary

用于 stats 概述的容器。

Container

total

统计数据摘要的容器聚合了总数。

Container

如果成功,响应中包含请求的信息。

1.30. 删除使用信息

删除使用信息.如果未指定日期,将删除所有使用信息。

功能

`usage=write`

语法

DELETE /admin/usage?format=json HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME

表 1.50. 请求参数

名称描述类型示例必需

uid

请求信息的用户。

字符串

foo_user

start

指定所请求数据的开始时间的日期和(可选)时间。

字符串

2012-09-25 16:00:00

end

指定请求数据的结束时间(无包含)的日期和(可选)时间。

字符串

2012-09-25 16:00:00

remove-all

未指定 uid 时需要此项,以便确认多用户数据删除。

布尔值

True [False]

1.31. 标准错误响应

下表详细介绍了标准错误响应及其描述。

名称描述Code

AccessDenied

访问被拒绝.

403 禁止

InternalError

内部服务器错误.

500 个内部服务器错误

NoSuchUser

用户不存在.

404 未找到

NoSuchBucket

bucket 不存在。

404 未找到

NoSuchKey

没有这样的访问密钥。

404 未找到

第 2 章 Ceph 对象网关和 S3 API

作为开发人员,您可以使用与 Amazon S3 数据访问模型兼容的 RESTful 应用程序编程接口(API)。您可以通过 Ceph 对象网关管理存储在红帽 Ceph 存储集群中的 bucket 和对象。

2.1. 先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • RESTful 客户端。

2.2. S3 限制

重要

以下限制应谨慎使用。您的硬件选择会有影响,因此您应该始终与您的红帽客户团队讨论这些要求。

  • 使用 Amazon S3 时的最大对象大小: 单个 Amazon S3 对象的大小可从最小 0B 到最多 5TB 之间。单个 PUT 中可以上传的最大对象为 5GB。对于大于 100MB 的对象,您应该考虑使用多部分上传功能。
  • 使用 Amazon S3 时的最大元数据大小 :对可应用到对象的用户元数据总大小没有定义限制,但单个 HTTP 请求仅限于 16,000 个字节。
  • 红帽 Ceph 存储集群产生的数据开销以存储 S3 对象和元数据: 这里估计为 200-300 字节,加上对象名称的长度。版本的对象会根据版本数量消耗额外的空间。另外,在多部分上传和其他事务更新期间会产生瞬时的开销,但这些开销会在垃圾回收过程中恢复。

其它资源

2.3. 使用 S3 API 访问 Ceph 对象网关

作为开发人员,您必须配置对 Ceph 对象网关和安全令牌服务(STS)的访问,然后才能开始使用 Amazon S3 API。

2.3.1. 先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • 正在运行的 Ceph 对象网关.
  • RESTful 客户端。

2.3.2. S3 身份验证

对 Ceph 对象网关的请求可以进行身份验证,也可以未经身份验证。Ceph 对象网关假定未经身份验证的请求由匿名用户发送。Ceph 对象网关支持 Canned ACL。

在大多数用例中,客户端使用现有开源库,如 Amazon SDK 的 AmazonS3Client 和 Python Boto。使用开源库,您只需传递访问密钥和密钥,并且库会为您构建请求标头和身份验证签名。但是,您可以创建请求并签署请求。

对请求进行身份验证需要先在请求中包含 access key 和一个基本 64 编码的消息身份验证代码(HMAC),然后才能发送到 Ceph 对象网关服务器。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 替换为访问密钥 ID 的值,后跟冒号(:)。将 HASH_OF_HEADER_AND_SECRET 替换为规范化标头字符串的哈希值和与访问密钥 ID 对应的 secret。

生成标头字符串和 secret 的散列

生成标头字符串和 secret 的散列:

  1. 获取标头字符串的值。
  2. 将请求标头字符串规范化为规范形式。
  3. 使用 SHA-1 哈希算法生成 HMAC。
  4. hmac 结果编码为 base-64。

规范化标头

将标头规范化为规范形式:

  1. 获取所有 content- 标头。
  2. 删除除 content-typecontent-md5 以外的所有 content- 标头。
  3. 确定 content- 标头名称为小写。
  4. 按字典对 content- 标头排序。
  5. 确定您有一个 Date 标头 AND 确保指定日期使用 GMT 而不是偏移。
  6. 获取以 x-amz- 开头的所有标头。
  7. 确定 x-amz- 标头都是小写。
  8. 按字典对 x-amz- 标头排序。
  9. 将相同字段名称的多个实例组合到一个字段,并使用逗号分隔字段值。
  10. 将标题值中的空格和换行符替换为单个空格。
  11. 删除冒号前后的空格。
  12. 在每个标头后面附加一个新行。
  13. 将标头重新合并到请求标头中。

使用 base-64 编码的 HMAC 字符串替换 HASH-OF-HEADER-AND-SECRET

其它资源

2.3.3. S3 服务器端加密

Ceph 对象网关支持为 S3 应用编程接口(API)对上载对象进行服务器端加密。服务器端加密意味着 S3 客户端以未加密的形式通过 HTTP 发送数据,而 Ceph 对象网关以加密的形式将数据存储在红帽 Ceph 存储群集中。

注意

红帽不支持静态大型对象(SLO)或动态大对象(DLO)的 S3 对象加密。

重要

若要使用加密,客户端请求 MUST 通过 SSL 连接发送请求。除非 Ceph 对象网关使用 SSL,否则红帽不支持从客户端进行 S3 加密。但是,出于测试目的,管理员可以在测试期间禁用 SSL,在运行时将 rgw_crypt_require_ssl 配置设置设置为 false,在 Ceph 配置文件中将其设置为 false,并在 Ansible 配置文件中将其设置为 false,并代表为 Ceph 对象网关设置 Ansible playbook。

在生产环境中,可能无法通过 SSL 发送加密的请求。在这种情况下,使用 HTTP 和服务器端加密发送请求。

有关如何使用服务器端加密配置 HTTP 的详情,请参考下面 的附加资源 部分。

管理加密密钥有两个选项:

客户提供的键

在使用客户提供的密钥时,S3 客户端会传递加密密钥以及每个请求来读取或写入加密数据。客户负责管理这些密钥。客户必须记住用于加密每个对象的 Ceph 对象网关的关键是什么。

Ceph 对象网关根据 Amazon SSE-C 规范在 S3 API 中实施客户提供的关键行为。

由于客户处理密钥管理,并且 S3 客户端将密钥传递到 Ceph 对象网关,因此 Ceph 对象网关不需要特殊配置来支持这种加密模式。

密钥管理服务

在使用密钥管理服务时,安全密钥管理服务存储密钥,Ceph 对象网关则按需检索密钥,为数据加密或解密请求提供服务。

Ceph 对象网关根据 Amazon SSE-KMS 规范在 S3 API 中实施关键管理服务行为。

重要

目前,唯一经过测试的密钥管理实施使用 OpenStack Barbican。但是,OpenStack Barbican 是一个技术预览,不支持在生产环境中使用。

2.3.4. S3 访问控制列表

Ceph 对象网关支持 S3 兼容访问控制列表(ACL)功能。ACL 是一个访问权限授权列表,用于指定用户可在存储桶或对象上执行哪些操作。当应用到存储桶时,每个授权的含义和应用到对象时都有不同的含义:

表 2.1. 用户操作

权限bucketObject

READ

授予者可以列出 bucket 中的对象。

授权人可以读取对象。

WRITE

授权人可以在存储桶中写入或删除对象。

不适用

READ_ACP

授权人可以读取存储桶 ACL。

授权人可以读取对象 ACL。

WRITE_ACP

授权人可以编写存储桶 ACL。

授权人可以写入对象 ACL。

FULL_CONTROL

授予者对存储桶中对象具有完全权限。

授权人可以读取或写入对象 ACL。

2.3.5. 准备使用 S3 访问 Ceph 对象网关

在尝试访问网关服务器之前,您必须遵循 Ceph 对象网关节点上的一些前提条件。

警告

不要 修改 Ceph 配置文件以使用端口 80,而让 Civetweb 使用默认 Ansible 配置的端口 8080

先决条件

  • 安装 Ceph 对象网关软件.
  • Ceph 对象网关节点的根级别访问权限.

流程

  1. 作为 root,在防火墙中打开端口 8080:

    [root@rgw ~]# firewall-cmd --zone=public --add-port=8080/tcp --permanent
    [root@rgw ~]# firewall-cmd --reload
  2. 按照 对象网关配置和管理指南中所述,向 DNS 服务器添加一个通配符,以用于网关

    您还可以为本地 DNS 缓存设置网关节点。要做到这一点,请执行以下步骤:

    1. 作为 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 地址和 FQDN 替换 IP_OF_GATEWAY_NODEFQDN_OF_GATEWAY_NODE

    2. 作为 root,停止 NetworkManager:

      [root@rgw ~]# systemctl stop NetworkManager
      [root@rgw ~]# systemctl disable NetworkManager
    3. 作为 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 地址和 FQDN 替换 IP_OF_GATEWAY_NODEFQDN_OF_GATEWAY_NODE

    4. 验证子域请求:

      [user@rgw ~]$ ping mybucket.FQDN_OF_GATEWAY_NODE

      使用网关节点的 FQDN 替换 FQDN_OF_GATEWAY_NODE

      警告

      为本地 DNS 缓存设置网关服务器仅用于测试目的。执行此操作后,您将无法访问外部网络。强烈建议将正确的 DNS 服务器用于 Red Hat Ceph Storage 集群和网关节点。

  3. 按照 对象网关配置和管理指南中所述,创建 radosgw 用户以进行 S3 访问, 并复制生成的 access_keysecret_key。您将需要这些密钥才能进行 S3 访问和后续存储桶管理任务。

2.3.6. 使用 Ruby AWS S3 访问 Ceph 对象网关

您可以使用 Ruby 编程语言和 aws-s3 gem 访问 S3。在用于使用 Ruby AWS::S3 访问 Ceph 对象网关服务器的节点上执行下面介绍的步骤。

先决条件

  • 用户对 Ceph 对象网关的访问.
  • 访问 Ceph 对象网关的节点的根级别访问权限.
  • 互联网访问.

流程

  1. 安装 ruby 软件包:

    [root@dev ~]# yum install ruby
    注意

    以上命令将安装 ruby,它的必要依赖项,如 rubygemsruby-libs。如果 命令以某种方式未安装所有依赖项,请单独安装它们。

  2. 安装 aws-s3 Ruby 软件包:

    [root@dev ~]# gem install aws-s3
  3. 创建项目目录:

    [user@dev ~]$ mkdir ruby_aws_s3
    [user@dev ~]$ cd ruby_aws_s3
  4. 创建连接文件:

    [user@dev ~]$ vim conn.rb
  5. 将以下内容粘贴到 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。按照 红帽 Ceph 存储对象网关配置和管理指南中所述,将 MY-ACCESS -KEY 和 MY-SECRET-KEY 替换为您在创建 radosgw 用户以进行 S3 访问时生成的 access_key secret_key

    示例

    #!/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'
    )

    保存文件并退出编辑器。

  6. 使文件可执行:

    [user@dev ~]$ chmod +x conn.rb
  7. 运行该文件:

    [user@dev ~]$ ./conn.rb | echo $?

    如果您已在文件中正确提供了值,命令的输出将是 0

  8. 为创建存储桶创建新文件:

    [user@dev ~]$ vim create_bucket.rb

    将以下内容粘贴到文件中:

    #!/usr/bin/env ruby
    
    load 'conn.rb'
    
    AWS::S3::Bucket.create('my-new-bucket1')

    保存文件并退出编辑器。

  9. 使文件可执行:

    [user@dev ~]$ chmod +x create_bucket.rb
  10. 运行该文件:

    [user@dev ~]$ ./create_bucket.rb

    如果命令的输出是 true,则表示存储桶 'my-new-bucket1'was 已成功创建。

  11. 为列出拥有的存储桶创建新文件:

    [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

    保存文件并退出编辑器。

  12. 使文件可执行:

    [user@dev ~]$ chmod +x list_owned_buckets.rb
  13. 运行该文件:

    [user@dev ~]$ ./list_owned_buckets.rb

    输出应类似如下:

    my-new-bucket1 2020-01-21 10:33:19 UTC
  14. 为创建对象创建新文件:

    [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'
    )

    保存文件并退出编辑器。

  15. 使文件可执行:

    [user@dev ~]$ chmod +x create_object.rb
  16. 运行该文件:

    [user@dev ~]$ ./create_object.rb

    这将创建一个带有字符串 Hello World! 的文件 hello.txt

  17. 为列出存储桶的内容创建新文件:

    [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

    保存文件并退出编辑器。

  18. 使文件可执行。

    [user@dev ~]$ chmod +x list_bucket_content.rb
  19. 运行该文件:

    [user@dev ~]$ ./list_bucket_content.rb

    输出将类似如下:

    hello.txt    12    Fri, 22 Jan 2020 15:54:52 GMT
  20. 为删除空存储桶创建新文件:

    [user@dev ~]$ vim del_empty_bucket.rb

    将以下内容粘贴到文件中:

    #!/usr/bin/env ruby
    
    load 'conn.rb'
    
    AWS::S3::Bucket.delete('my-new-bucket1')

    保存文件并退出编辑器。

  21. 使文件可执行:

    [user@dev ~]$ chmod +x del_empty_bucket.rb
  22. 运行该文件:

    [user@dev ~]$ ./del_empty_bucket.rb | echo $?

    如果成功删除存储桶,该命令将以输出返回 0

    注意

    编辑 create_bucket.rb 文件以创建空存储桶,例如: my-new-bucket4my-new-bucket5。接下来,在尝试删除空存储桶前,请相应地编辑上述 del_empty_bucket.rb 文件。

  23. 为删除非空存储桶创建新文件:

    [user@dev ~]$ vim del_non_empty_bucket.rb

    将以下内容粘贴到文件中:

    #!/usr/bin/env ruby
    
    load 'conn.rb'
    
    AWS::S3::Bucket.delete('my-new-bucket1', :force => true)

    保存文件并退出编辑器。

  24. 使文件可执行:

    [user@dev ~]$ chmod +x del_non_empty_bucket.rb
  25. 运行该文件:

    [user@dev ~]$ ./del_non_empty_bucket.rb | echo $?

    如果成功删除存储桶,该命令将以输出返回 0

  26. 为删除对象创建新文件:

    [user@dev ~]$ vim delete_object.rb

    将以下内容粘贴到文件中:

    #!/usr/bin/env ruby
    
    load 'conn.rb'
    
    AWS::S3::S3Object.delete('hello.txt', 'my-new-bucket1')

    保存文件并退出编辑器。

  27. 使文件可执行:

    [user@dev ~]$ chmod +x delete_object.rb
  28. 运行该文件:

    [user@dev ~]$ ./delete_object.rb

    这将删除对象 hello.txt

2.3.7. 使用 Ruby AWS SDK 访问 Ceph 对象网关

您可以使用 Ruby 编程语言和 aws-sdk gem 访问 S3。在用于使用 Ruby AWS::SDK 访问 Ceph 对象网关服务器的节点上执行下面介绍的步骤。

先决条件

  • 用户对 Ceph 对象网关的访问.
  • 访问 Ceph 对象网关的节点的根级别访问权限.
  • 互联网访问.

流程

  1. 安装 ruby 软件包:

    [root@dev ~]# yum install ruby
    注意

    以上命令将安装 ruby,它的必要依赖项,如 rubygemsruby-libs。如果 命令以某种方式未安装所有依赖项,请单独安装它们。

  2. 安装 aws-sdk Ruby 软件包:

    [root@dev ~]# gem install aws-sdk
  3. 创建项目目录:

    [user@dev ~]$ mkdir ruby_aws_sdk
    [user@dev ~]$ cd ruby_aws_sdk
  4. 创建连接文件:

    [user@dev ~]$ vim conn.rb
  5. 将以下内容粘贴到 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。按照 红帽 Ceph 存储对象网关配置和管理指南中所述,将 MY-ACCESS -KEY 和 MY-SECRET-KEY 替换为您在创建 radosgw 用户以进行 S3 访问时生成的 access_key secret_key

    示例

    #!/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'
    )

    保存文件并退出编辑器。

  6. 使文件可执行:

    [user@dev ~]$ chmod +x conn.rb
  7. 运行该文件:

    [user@dev ~]$ ./conn.rb | echo $?

    如果您已在文件中正确提供了值,命令的输出将是 0

  8. 为创建存储桶创建新文件:

    [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')

    保存文件并退出编辑器。

  9. 使文件可执行:

    [user@dev ~]$ chmod +x create_bucket.rb
  10. 运行该文件:

    [user@dev ~]$ ./create_bucket.rb

    如果命令的输出是 true,这意味着已成功创建存储桶 my-new-bucket2

  11. 为列出拥有的存储桶创建新文件:

    [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

    保存文件并退出编辑器。

  12. 使文件可执行:

    [user@dev ~]$ chmod +x list_owned_buckets.rb
  13. 运行该文件:

    [user@dev ~]$ ./list_owned_buckets.rb

    输出应类似如下:

    my-new-bucket2 2020-01-21 10:33:19 UTC
  14. 为创建对象创建新文件:

    [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'
    )

    保存文件并退出编辑器。

  15. 使文件可执行:

    [user@dev ~]$ chmod +x create_object.rb
  16. 运行该文件:

    [user@dev ~]$ ./create_object.rb

    这将创建一个带有字符串 Hello World! 的文件 hello.txt

  17. 为列出存储桶的内容创建新文件:

    [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

    保存文件并退出编辑器。

  18. 使文件可执行。

    [user@dev ~]$ chmod +x list_bucket_content.rb
  19. 运行该文件:

    [user@dev ~]$ ./list_bucket_content.rb

    输出将类似如下:

    hello.txt    12    Fri, 22 Jan 2020 15:54:52 GMT
  20. 为删除空存储桶创建新文件:

    [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')

    保存文件并退出编辑器。

  21. 使文件可执行:

    [user@dev ~]$ chmod +x del_empty_bucket.rb
  22. 运行该文件:

    [user@dev ~]$ ./del_empty_bucket.rb | echo $?

    如果成功删除存储桶,该命令将以输出返回 0

    注意

    编辑 create_bucket.rb 文件以创建空存储桶,例如: my-new-bucket6my-new-bucket7。接下来,在尝试删除空存储桶前,请相应地编辑上述 del_empty_bucket.rb 文件。

  23. 创建新文件以删除非空存储桶:

    [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')

    保存文件并退出编辑器。

  24. 使文件可执行:

    [user@dev ~]$ chmod +x del_non_empty_bucket.rb
  25. 运行该文件:

    [user@dev ~]$ ./del_non_empty_bucket.rb | echo $?

    如果成功删除存储桶,该命令将以输出返回 0

  26. 为删除对象创建新文件:

    [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')

    保存文件并退出编辑器。

  27. 使文件可执行:

    [user@dev ~]$ chmod +x delete_object.rb
  28. 运行该文件:

    [user@dev ~]$ ./delete_object.rb

    这将删除对象 hello.txt

2.3.8. 使用 PHP 访问 Ceph 对象网关

您可以使用 PHP 脚本来访问 S3。此流程提供了一些执行各种任务(如删除存储桶或对象)的示例 PHP 脚本。

重要

下面的例子使用 php v5.4.16aws-sdk v2.8.24 测试。不要 将最新版本的 aws-sdk 用于 php,因为它需要 php >= 5.5+php 5.5RHEL 7 的默认存储库中不可用。如果要使用 php 5.5,您必须启用 epel 和其他第三方软件仓库。另外,php 5.5 和最新版本 aws-sdk 的配置选项是不同的。

先决条件

  • 对开发工作站的根级别访问权限.
  • 互联网访问.

流程

  1. 安装 php 软件包:

    [root@dev ~]# yum install php
  2. 下载 用于 PHP 的 aws-sdk 的 zip 归档并解压缩它。
  3. 创建项目目录:

    [user@dev ~]$ mkdir php_s3
    [user@dev ~]$ cd php_s3
  4. 将提取的 aws 目录复制到项目目录中。例如:

    [user@dev ~]$ cp -r ~/Downloads/aws/ ~/php_s3/
  5. 创建连接文件:

    [user@dev ~]$ vim conn.php
  6. 将以下内容粘贴到 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。按照 红帽 Ceph 存储对象网关配置和管理指南中所述,将 MY_ACCESS _KEY 和 MY_SECRET_KEY 替换为 access_key secret_key,后者在创建 radosgw 用户以进行 S3 访问时生成。将 PATH_TO_AWS 替换为您复制到 php 项目目录中提取的 aws 目录的绝对路径。

    保存文件并退出编辑器。

  7. 运行该文件:

    [user@dev ~]$ php -f conn.php | echo $?

    如果您已在文件中正确提供了值,命令的输出将是 0

  8. 为创建存储桶创建新文件:

    [user@dev ~]$ vim create_bucket.php

    将以下内容粘贴到新文件中:

    语法

    <?php
    
    include 'conn.php';
    
    client->createBucket(array('Bucket' => 'my-new-bucket3'));
    
    ?>

    保存文件并退出编辑器。

  9. 运行该文件:

    [user@dev ~]$ php -f create_bucket.php
  10. 为列出拥有的存储桶创建新文件:

    [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";
    }
    
    ?>

    保存文件并退出编辑器。

  11. 运行该文件:

    [user@dev ~]$ php -f list_owned_buckets.php

    输出应类似如下:

    my-new-bucket3 2020-01-21 10:33:19 UTC
  12. 首先通过创建名为 hello.txt 的源文件来创建对象:

    [user@dev ~]$ echo "Hello World!" > hello.txt
  13. 创建新的 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);
    
    ?>

    保存文件并退出编辑器。

  14. 运行该文件:

    [user@dev ~]$ php -f create_object.php

    这将在存储桶 my-new-bucket3 中创建对象 hello.txt

  15. 为列出存储桶的内容创建新文件:

    [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";
    }
    ?>

    保存文件并退出编辑器。

  16. 运行该文件:

    [user@dev ~]$ php -f list_bucket_content.php

    输出结果类似如下:

    hello.txt    12    Fri, 22 Jan 2020 15:54:52 GMT
  17. 为删除空存储桶创建新文件:

    [user@dev ~]$ vim del_empty_bucket.php

    将以下内容粘贴到文件中:

    语法

    <?php
    
    include 'conn.php';
    
    client->deleteBucket(array('Bucket' => 'my-new-bucket3'));
    ?>

    保存文件并退出编辑器。

  18. 运行该文件:

    [user@dev ~]$ php -f del_empty_bucket.php | echo $?

    如果成功删除存储桶,该命令将以输出返回 0

    注意

    编辑 create_bucket.php 文件以创建空存储桶,例如: my-new-bucket4my-new-bucket5。接下来,在尝试删除空存储桶前,请相应地编辑上述 del_empty_bucket.php 文件。

    重要

    PHP 2 及新版本的 aws-sdk 目前不支持删除非空存储桶。

  19. 为删除对象创建新文件:

    [user@dev ~]$ vim delete_object.php

    将以下内容粘贴到文件中:

    语法

    <?php
    
    include 'conn.php';
    
    client->deleteObject(array(
        'Bucket' => 'my-new-bucket3',
        'Key'    => 'hello.txt',
    ));
    ?>

    保存文件并退出编辑器。

  20. 运行该文件:

    [user@dev ~]$ php -f delete_object.php

    这将删除对象 hello.txt

2.3.9. 安全令牌服务

Amazon Web Services 的安全令牌服务(STS)返回一组用于对用户进行身份验证的临时安全凭证。Ceph 对象网关实施 STS 应用编程接口(API)的子集,为身份和访问管理(IAM)提供临时凭据。使用这些临时凭据时,可利用 Ceph 对象网关中的 STS 引擎来验证 S3 调用。您可以使用 IAM 策略(传递给 STS API 的参数)进一步限制临时凭证。

2.3.9.1. 安全令牌服务应用程序编程接口

Ceph 对象网关实施以下安全令牌服务(STS)应用编程接口(API):

AssumeRole

此 API 返回一组用于跨帐户访问的临时凭证。这些临时凭证允许同时使用与 角色 关联的权限策略,以及与 AssumeRole API 关联 的策略。RoleArnRoleSessionName 请求参数是必需的,但其他请求参数是可选的。

RoleArn
描述
要假定的 Amazon 资源名称(ARN)的角色,长度为 20 到 2048 个字符。
类型
字符串
必需
RoleSessionName
描述
识别要假定的角色会话名称。当不同的主体或不同原因假定角色角色时,角色会话名称可以唯一地标识会话。此参数的长度为 2 到 64 个字符。允许 =,. @- 字符,但不允许有空格。
类型
字符串
必需
Policy
描述
以 JSON 格式提供的身份和访问管理策略(IAM),供内嵌会话使用。此参数的值的长度为 1 到 2048 个字符。
类型
字符串
必需
DurationSeconds
描述
会话的持续时间(以秒为单位),最小值为 900 秒,最大值为 43200 秒。默认值为 3600 秒。
类型
整数
必需
ExternalId
描述
假定其他帐户的角色时,请提供唯一外部标识符(如果可用)。此参数的长度为 2 到 1224 个字符。
类型
字符串
必需
SerialNumber
描述
用户的标识号来自其关联的多因素验证(MFA)设备。参数的值可以是硬件设备的序列号或虚拟设备,长度为 9 到 256 个字符。
类型
字符串
必需
TokenCode
描述
如果信任策略需要 MFA,则由多因素身份验证(MFA)设备生成的值。如果需要 MFA 设备,如果此参数的值为空或过期,则 AssumeRole 调用返回 "access denied" 错误消息。此参数的值具有 6 个字符的固定长度。
类型
字符串
必需

AssumeRoleWithWebIdentity

此 API 为已由应用进行身份验证的用户(如 OpenID Connect 或 OAuth 2.0 身份提供商)返回一组临时凭证。RoleArnRoleSessionName 请求参数是必需的,但其他请求参数是可选的。

RoleArn
描述
要假定的 Amazon 资源名称(ARN)的角色,长度为 20 到 2048 个字符。
类型
字符串
必需
RoleSessionName
描述
识别要假定的角色会话名称。当不同的主体或不同原因假定角色角色时,角色会话名称可以唯一地标识会话。此参数的长度为 2 到 64 个字符。允许 =,. @- 字符,但不允许有空格。
类型
字符串
必需
Policy
描述
以 JSON 格式提供的身份和访问管理策略(IAM),供内嵌会话使用。此参数的值的长度为 1 到 2048 个字符。
类型
字符串
必需
DurationSeconds
描述
会话的持续时间(以秒为单位),最小值为 900 秒,最大值为 43200 秒。默认值为 3600 秒。
类型
整数
必需
ProviderId
描述
来自身份提供程序的域名的完全限定主机组件。此参数的值仅对 OAuth 2.0 访问令牌有效,长度为 4 到 2048 个字符。
类型
字符串
必需
WebIdentityToken
描述
从身份提供程序提供的 OpenID Connect 身份提供程序或 OAuth 2.0 访问令牌。此参数的值长度为 4 到 2048 个字符。
类型
字符串
必需

其它资源

2.3.9.2. 配置安全令牌服务

配置安全令牌服务(STS),以使用 Ceph Ansible 与 Ceph 对象网关搭配使用。

注意

S3 和 STS API 在同一命名空间中共存,它们可以从 Ceph 对象网关中的同一端点访问。

先决条件

  • Ceph Ansible 管理节点.
  • 正在运行的红帽 Ceph 存储群集.
  • 正在运行的 Ceph 对象网关.

流程

  1. 打开 编辑 group_vars/rgws.yml 文件。

    1. 添加以下行:

      rgw_sts_key = STS_KEY
      rgw_s3_auth_use_sts = true

      替换:

      • STS_KEY 以及用于加密会话令牌的密钥.
  2. 保存对 group_vars/rgws.yml 文件的更改。
  3. 重新运行适当的 Ceph Ansible playbook:

    1. 裸机 部署:

      [user@admin ceph-ansible]$ ansible-playbook site.yml --limit rgws
    2. 容器 部署:

      [user@admin ceph-ansible]$ ansible-playbook site-docker.yml --limit rgws

2.3.9.3. 为 OpenID Connect 供应商创建用户

要在 Ceph 对象网关和 OpenID Connect 提供程序之间建立信任,请创建一个用户实体和角色信任策略。

先决条件

  • 用户级访问 Ceph 对象网关节点.

流程

  1. 创建一个新的 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

  2. 配置 Ceph 用户功能:

    语法

    radosgw-admin caps add --uid="USER_NAME" --caps="oidc-provider=*"

    示例

    [user@rgw ~]$ radosgw-admin caps add --uid="TESTER" --caps="oidc-provider=*"

  3. 使用安全令牌服务(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 字段匹配。

2.3.9.4. 获取 OpenID Connect 供应商的指纹

要获取 OpenID Connect 提供程序(IDP)配置文档:

先决条件

  • 安装 opensslcurl 软件包。

流程

  1. 从 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 .

  2. 获取 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 .

  3. 从上一命令复制"x5c"响应结果并将其粘贴到 certificate.crt 文件中。在开始包含 —–BEGIN CERTIFICATE—–,并在末尾包括 —–END CERTIFICATE—–
  4. 获取证书指纹:

    语法

    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

  5. 从 SHA1 指纹中删除所有冒号,并将它用作在 IAM 请求中创建 IDP 实体的输入。

2.3.9.5. 配置和使用带有 Keystone 的 STS Lite(技术预览)

Amazon 安全令牌服务(STS)和 S3 API 在同一命名空间中共存。STS 选项可以与 Keystone 选项结合使用。

注意

S3 和 STS API 都可以在 Ceph 对象网关中使用相同的端点来访问。

先决条件

  • 红帽 Ceph 存储 3.2 或更高版本.
  • 正在运行的 Ceph 对象网关.
  • 安装 Boto Python 模块,版本 3 或更高版本。

流程

  1. 使用以下选项打开并编辑 group_vars/rgws.yml 文件:

    rgw_sts_key = STS_KEY
    rgw_s3_auth_use_sts = true

    替换:

    • STS_KEY 以及用于加密会话令牌的密钥.
  2. 重新运行适当的 Ceph Ansible playbook:

    1. 裸机 部署:

      [user@admin ceph-ansible]$ ansible-playbook site.yml --limit rgws
    2. 容器 部署:

      [user@admin ceph-ansible]$ ansible-playbook site-docker.yml --limit rgws
  3. 生成 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                       |
    +------------+--------------------------------------------------------+

  4. 使用生成的凭据,通过 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
    )

  5. 获取临时凭证可用于进行 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'],
      )

  6. 创建新的 S3Access 角色并配置策略。

    1. 使用管理 CAPS 为用户分配:

      语法

      radosgw-admin caps add --uid="USER" --caps="roles=*"

      示例

      [user@client]$ radosgw-admin caps add --uid="gwadmin" --caps="roles=*"

    2. 创建 S3Access 角色:

      语法

      radosgw-admin role create --role-name=ROLE_NAME --path=PATH --assume-role-policy-doc=TRUST_POLICY_DOC

      示例

      [user@client]$ 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\"\]\}\]\}

    3. 将权限策略附加到 S3Access 角色:

      语法

      radosgw-admin role-policy put --role-name=ROLE_NAME --policy-name=POLICY_NAME --policy-doc=PERMISSION_POLICY_DOC

      示例

      [user@client]$ 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\"\}\]\}

    4. 现在,另一个用户可以承担 gwadmin 用户的角色。例如,gwuser 用户可以假定 gwadmin 用户的权限。
    5. 记录假设用户的 access_keysecret_key 值。

      示例

      [user@client]$ radosgw-admin user info --uid=gwuser | grep -A1 access_key

  7. 使用 AssumeRole API 调用,提供来自假设用户的 access_keysecret_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 模块的更多信息,请参见《 红帽 Ceph 存储对象网关指南》 中的 测试 S3 访问 部分。
  • 如需更多信息,请参阅《 红帽 Ceph 存储对象网关指南》 中的 创建用户 部分。

2.3.9.6. 围绕将 STS Lite 与 Keystone 搭配使用的限制(技术预览)

Keystone 的一个限制是它不支持 STS 请求。另一个限制是有效负载哈希不在请求中。要解决这两个限制,必须修改 Boto 身份验证代码。

先决条件

  • 正在运行的红帽 Ceph 存储集群 3.2 或更高版本。
  • 正在运行的 Ceph 对象网关.
  • 安装 Boto Python 模块,版本 3 或更高版本.

流程

  1. 打开并编辑 Boto 的 auth.py 文件。

    1. 在代码块中添加以下四行:

      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
    2. 在代码块中添加以下两行:

      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 模块的更多信息,请参见《红帽 Ceph 存储 对象网关指南》 中的 测试 S3 访问 部分。

2.4. S3 bucket 操作

作为开发人员,您可以通过 Ceph 对象网关使用 Amazon S3 应用程序编程接口(API)执行存储桶操作。

下表列出了 bucket 的 Amazon S3 功能操作,以及功能的支持状态。

表 2.2. bucket 操作

功能Status备注

列出 Buckets

支持

 

创建 Bucket

支持

不同的一组可执行 ACL.

bucket 生命周期

部分支持

Expiration支持、NoncurrentVersionExpirationAbortIncompleteMultipartUpload

放置 Bucket Lifecycle

部分支持

Expiration支持、NoncurrentVersionExpirationAbortIncompleteMultipartUpload

删除 Bucket 生命周期

支持

 

获取 Bucket 对象

支持

 

获取 Bucket 通知

支持

 

bucket 位置

支持

 

获取 Bucket 版本

支持

 

放置 Bucket 版本

支持

 

删除 Bucket

支持

 

获取 Bucket ACL

支持

不同的一组可执行 ACL

放置 Bucket ACL

支持

不同的一组可执行 ACL

获取 Bucket cors

支持

 

放置 Bucket cors

支持

 

删除 Bucket cors

支持

 

列出 Bucket 对象版本

支持

 

head Bucket

支持

 

列出 Bucket 多部分上传

支持

 

bucket 策略

部分支持

 

获取 Bucket 请求付款

支持

 

放置 Bucket 请求付款

支持

 

多租户 Bucket 操作

支持

 

2.4.1. 先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • RESTful 客户端。

2.4.2. 访问存储桶主机名

访问 bucket 有两种不同的模式。第一种和首选方法将 bucket 识别为 URI 中的顶级目录。

示例

GET /mybucket HTTP/1.1
Host: cname.domain.com

第二种方法通过虚拟 bucket 主机名识别 bucket。

示例

GET / HTTP/1.1
Host: mybucket.cname.domain.com

提示

红帽首选第一种方法,因为第二种方法需要昂贵的域认证和 DNS 通配符。

2.4.3. S3 list bucket

GET / 返回由用户创建请求的存储桶列表。GET / 仅返回由经过身份验证的用户创建的 bucket。您不能发出匿名请求。

语法

GET / HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

表 2.3. 响应实体

名称类型描述

Buckets

Container

用于存储桶列表的容器.

Bucket

Container

用于存储桶信息的容器.

Name

字符串

bucket 名称.

CreationDate

Date

创建存储桶的 UTC 时间。

ListAllMyBucketsResult

Container

结果的容器。

Owner

Container

bucket 所有者 IDDisplayName 的容器。

ID

字符串

bucket 所有者的 ID。

DisplayName

字符串

bucket 所有者的显示名称。

2.4.4. S3 返回存储桶对象列表

返回存储桶对象列表。

语法

GET /BUCKET?max-keys=25 HTTP/1.1
Host: cname.domain.com

表 2.4. 参数

名称类型描述

prefix

字符串

仅返回包含指定前缀的对象。

delimiter

字符串

前缀和对象名称其余部分之间的分隔符。

marker

字符串

返回的对象列表的起始索引。

max-keys

整数

要返回的最大密钥数。默认值为 1000。

表 2.5. HTTP 响应

HTTP 状态状态代码描述

200

确定

检索的存储桶

GET /BUCKET 使用以下字段为存储桶返回容器:

表 2.6. bucket 响应实体

名称类型描述

ListBucketResult

实体

对象列表的容器。

Name

字符串

返回内容的 bucket 的名称。

Prefix

字符串

对象密钥的前缀。

Marker

字符串

返回的对象列表的起始索引。

MaxKeys

整数

返回的最大密钥数。

Delimiter

字符串

如果设置,具有相同前缀的对象将出现在 CommonPrefixes 列表中。

IsTruncated

布尔值

如果为 true,则只返回存储桶内容的一个子集。

CommonPrefixes

Container

如果多个对象包含相同的前缀,它们将显示在此列表中。

ListBucketResult 包含对象,每个对象都位于 Contents 容器中。

表 2.7. 对象响应实体

名称类型描述

Contents

Object

对象的容器。

Key

字符串

对象的密钥。

LastModified

Date

对象上次修改的日期/时间.

ETag

字符串

对象的 MD-5 哈希。(实体标签)

Size

整数

对象的大小。

StorageClass

字符串

应始终返回 STANDARD

2.4.5. S3 创建新存储桶

创建新存储桶。要创建存储桶,您必须有一个用户 ID 和一个有效的 AWS 访问密钥 ID 来验证请求。您不能以匿名用户身份创建存储桶。

约束

通常,存储桶名称应遵循域名约束。

  • bucket 名称必须唯一。
  • bucket 名称必须以小写字母开头和结尾。
  • bucket 名称可以包含短划线(-)。

语法

PUT /<bucket> HTTP/1.1
Host: cname.domain.com
x-amz-acl: public-read-write

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

表 2.8. 参数

名称描述有效值必需

x-amz-acl

Canned ACL.

private, public-read,public-read-write, authenticated-read

HTTP 响应

如果 bucket 名称唯一,则在限制和未使用的情况下操作将成功。如果已存在具有相同名称的 bucket,并且该用户是 bucket 所有者,则操作将成功。如果存储桶名称已在使用,则该操作将失败。

HTTP 状态状态代码描述

409

BucketAlreadyExists

bucket 已存在于不同用户的所有权下。

2.4.6. S3 删除存储桶

删除存储桶.您可以在成功删除存储桶后重复使用存储桶名称。

语法

DELETE /<bucket> HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

表 2.9. HTTP 响应

HTTP 状态状态代码描述

204

无内容

bucket 已移除.

2.4.7. S3 bucket 生命周期

您可以使用存储桶生命周期配置来管理对象,以便在其整个生命周期内高效地存储它们。Ceph 对象网关中的 S3 API 支持 AWS bucket 生命周期操作的一个子集:

  • Expiration:这定义 bucket 中对象的寿命。对象应处于活动状态或到期日期的天数,即 Ceph 对象网关将删除对象的时间。如果 bucket 不启用版本控制,Ceph 对象网关将永久删除对象。如果 bucket 启用版本控制,Ceph 对象网关将为当前版本创建删除标记,然后删除当前版本。
  • NoncurrentVersionExpiration:这定义了存储桶中非当前对象版本的生命周期。要使用此功能,存储桶必须启用版本控制。非当前对象应处于活动状态需要天数,此时 Ceph 对象网关将删除非当前对象。
  • AbortIncompleteMultipartUpload:此定义在中断之前,不完整的多部分上传的天数应当进行。

生命周期配置包含一个或多个使用 <Rule> 元素的规则。

示例

<LifecycleConfiguration>
    <Rule>
      <Prefix/>
      <Status>Enabled</Status>
      <Expiration>
        <Days>10</Days>
      </Expiration>
    </Rule>
</LifecycleConfiguration>

生命周期规则可根据您在生命周期规则中指定的 <Filter> 元素应用到存储桶中的所有对象或对象子集。您可以通过多种方式指定过滤器:

  • 密钥前缀
  • 对象标签
  • 密钥前缀和一个或多个对象标签

密钥前缀

您可以根据键名称前缀,将生命周期规则应用到对象子集。例如:指定 <keypre/> 适用于以 keypre/ 开头的对象:

<LifecycleConfiguration>
    <Rule>
        <Status>Enabled</Status>
        <Filter>
           <Prefix>keypre/</Prefix>
        </Filter>
    </Rule>
</LifecycleConfiguration>

您还可以将不同的生命周期规则应用到具有不同键前缀的对象:

<LifecycleConfiguration>
    <Rule>
        <Status>Enabled</Status>
        <Filter>
           <Prefix>keypre/</Prefix>
        </Filter>
    </Rule>
    <Rule>
        <Status>Enabled</Status>
        <Filter>
           <Prefix>mypre/</Prefix>
        </Filter>
    </Rule>
</LifecycleConfiguration>

对象标签

您可以使用 <Key><Value> 元素将生命周期规则应用到带有特定标签的对象:

<LifecycleConfiguration>
    <Rule>
        <Status>Enabled</Status>
        <Filter>
           <Tag>
              <Key>key</Key>
              <Value>value</Value>
           </Tag>
        </Filter>
    </Rule>
</LifecycleConfiguration>

前缀和一个或多个标签

在生命周期规则中,您可以根据密钥前缀和一个或多个标签指定过滤器。它们必须包含在 <And> 元素中。过滤器只能有一个前缀,以及零个或多个标签:

<LifecycleConfiguration>
    <Rule>
        <Status>Enabled</Status>
        <Filter>
          <And>
             <Prefix>key-prefix</Prefix>
             <Tag>
                <Key>key1</Key>
                <Value>value1</Value>
             </Tag>
             <Tag>
                <Key>key2</Key>
                <Value>value2</Value>
             </Tag>
              ...
          </And>
        </Filter>
    </Rule>
</LifecycleConfiguration>

其它资源

2.4.8. S3 GET bucket 生命周期

要获取存储桶生命周期,请使用 GET 并指定一个目标存储桶。

语法

GET /<bucket>?lifecycle HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

请求标头

如需更多信息,请参阅 通用请求 标头。

响应

响应中包含 bucket 生命周期及其元素。

2.4.9. S3 创建或替换存储桶生命周期

要创建或替换存储桶生命周期,请使用 PUT 并指定目标存储桶和生命周期配置。Ceph 对象网关仅支持 S3 生命周期功能的子集。

语法

PUT /<bucket>?lifecycle HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_
<LifecycleConfiguration>
  <Rule>
    <Expiration>
      <Days>10</Days>
    </Expiration>
  </Rule>
    ...
  <Rule>
  </Rule>
</LifecycleConfiguration>

表 2.10. 请求标头

名称描述有效值必需

content-md5

消息的 base64 编码的 MD-5 哈希。

字符串无默认值或限制。

其它资源

2.4.10. S3 删除存储桶生命周期

要删除存储桶生命周期,使用 DELETE 并指定一个目标存储桶。

语法

DELETE /<bucket>?lifecycle HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

请求标头

请求不包含任何特殊元素。

响应

响应返回常见响应状态。

其它资源

  • 请参阅 Amazon S3 通用请求标头 的附录 A
  • 请参阅 附录 B 以了解 Amazon S3 通用响应状态代码。

2.4.11. S3 bucket 通知

notification 子资源返回存储桶通知配置或空 NotificationConfiguration 元素。调用者必须是 bucket 所有者。

语法

Get /<bucket>?notification HTTP/1.1
Host: cname.domain.com
Date: date
Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

Response 示例

<NotificationConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <TopicConfiguration>
    <Id>ID</Id>
    <Topic>topic</Topic>
    <Event>s3:event</Event>
  </TopicConfiguration>
</NotificationConfiguration>

2.4.12. S3 get bucket 位置

检索 bucket 的 zone group。用户需要成为 bucket 所有者才能调用此调用。通过在 PUT 请求期间提供 LocationConstraint,存储桶可能会受一个 zone group 的限制。

location 子资源添加到存储桶资源,如下所示。

语法

GET /<bucket>?location HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

表 2.11. 响应实体

名称类型描述

LocationConstraint

字符串

bucket 所在的 zone group,默认 zone group 的空字符串

2.4.13. S3 get bucket 版本控制

检索 bucket 的版本状态。用户需要成为 bucket 所有者才能调用此调用。

versioning 子资源添加到存储桶资源,如下所示。

语法

GET /<bucket>?versioning HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

2.4.14. S3 放置存储桶版本控制

此子资源设置现有存储桶的版本状态。用户需要成为 bucket 所有者,才能设置版本状态。如果存储桶上从未设置过版本状态,则它没有版本控制状态。执行 GET 版本控制请求不会返回版本控制状态值。

设置存储桶版本状态:

Enabled : 为存储桶中的对象启用版本控制。添加至 bucket 的所有对象都接收唯一的版本 ID。Suspended :禁用存储桶中对象的版本控制。添加至 bucket 的所有对象都接收版本 ID null。

语法

PUT /<bucket>?versioning HTTP/1.1

表 2.12. bucket 请求实体

名称类型描述

VersioningConfiguration

Container

请求的容器。

Status

字符串

设置存储桶的版本状态。有效值: Suspended/Enabled

2.4.15. S3 get bucket 访问控制列表

检索 bucket 访问控制列表。用户需要是存储桶所有者,或者被授予存储桶上的 READ_ACP 权限。

在存储桶请求中添加 acl 子资源,如下所示。

语法

GET /<bucket>?acl HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

表 2.13. 响应实体

名称类型描述

AccessControlPolicy

Container

用于响应的容器。

AccessControlList

Container

ACL 信息的容器。

Owner

Container

bucket 所有者 IDDisplayName 的容器。

ID

字符串

bucket 所有者的 ID。

DisplayName

字符串

bucket 所有者的显示名称。

Grant

Container

GranteePermission 的容器。

Grantee

Container

收到权限授权的用户 DisplayNameID 的容器。

Permission

字符串

Grantee 存储桶授予的权限。

2.4.16. S3放置存储桶访问控制列表

设置现有存储桶的访问控制。用户需要是存储桶所有者,或者被授予存储桶上的 WRITE_ACP 权限。

在存储桶请求中添加 acl 子资源,如下所示。

语法

PUT /<bucket>?acl HTTP/1.1

表 2.14. 请求实体

名称类型描述

AccessControlPolicy

Container

请求的容器。

AccessControlList

Container

ACL 信息的容器。

Owner

Container

bucket 所有者 IDDisplayName 的容器。

ID

字符串

bucket 所有者的 ID。

DisplayName

字符串

bucket 所有者的显示名称。

Grant

Container

GranteePermission 的容器。

Grantee

Container

收到权限授权的用户 DisplayNameID 的容器。

Permission

字符串

Grantee 存储桶授予的权限。

2.4.17. S3 get bucket cors

检索为存储桶设置的 cors 配置信息。用户需要是存储桶所有者,或者被授予存储桶上的 READ_ACP 权限。

在存储桶请求中添加 cors 子资源,如下所示。

语法

GET /<bucket>?cors HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

2.4.18. S3放置存储桶 cors

设置存储桶的 cors 配置。用户需要是存储桶所有者,或者被授予存储桶上的 READ_ACP 权限。

在存储桶请求中添加 cors 子资源,如下所示。

语法

PUT /<bucket>?cors HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

2.4.19. S3 删除存储桶 cors

删除为存储桶设置的 cors 配置信息。用户需要是存储桶所有者,或者被授予存储桶上的 READ_ACP 权限。

在存储桶请求中添加 cors 子资源,如下所示。

语法

DELETE /<bucket>?cors HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

2.4.20. S3 list bucket 对象版本

返回存储桶内所有对象的元数据列表。需要 READ 访问存储桶。

在存储桶请求中添加 versions 子资源,如下所示。

语法

GET /<bucket>?versions HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

您可以为 GET /<bucket>?versions 指定参数,但不需要这些参数。

表 2.15. 参数

名称类型描述

prefix

字符串

返回 in-progress 上传,其键包含指定的前缀。

delimiter

字符串

前缀和对象名称其余部分之间的分隔符。

key-marker

字符串

上传列表的开头标记。

max-keys

整数

in-progress 上传的最大数量。默认值为 1000。

version-id-marker

字符串

指定要开始列表的对象版本。

表 2.16. 响应实体

名称类型描述

KeyMarker

字符串

key-marker 请求参数指定的密钥标记(如果有)。

NextKeyMarker

字符串

如果 IsTruncatedtrue,则后续请求中使用的密钥标记。

NextUploadIdMarker

字符串

如果 IsTruncatedtrue,则后续请求中要使用的上传 ID 标记。

IsTruncated

布尔值

如果为 true,则只返回存储桶上传内容的子集。

Size

整数

上传的部分的大小。

DisplayName

字符串

所有者的显示名称.

ID

字符串

所有者的 ID.

Owner

Container

拥有该对象的 IDDisplayName 的容器。

StorageClass

字符串

用于存储生成的对象的方法。STANDARD 或者 REDUCED_REDUNDANCY

Version

Container

用于版本信息的 Container。

versionId

字符串

对象的版本 ID。

versionIdMarker

字符串

截断的响应中的密钥的最后一个版本。

2.4.21. S3 head bucket

在存储桶上调用 HEAD,以确定它是否存在以及调用者是否具有访问权限。如果存储桶存在且调用者有权限,则返回 200 OK ;如果存储桶不存在,则返回 404 Not Found ;如果存储桶存在,则返回 403 Forbidden,但调用者没有访问权限。

语法

HEAD /<bucket> HTTP/1.1
Host: cname.domain.com
Date: date
Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

2.4.22. S3 列出多部分上传

GET /?uploads 返回当前进行中多部分上传的列表,即,应用程序启动多部分上传,但该服务还没有完成所有上传。

语法

GET /<bucket>?uploads HTTP/1.1

您可以为 GET /<bucket>?uploads 指定参数,但不需要这些参数。

表 2.17. 参数

名称类型描述

prefix

字符串

返回 in-progress 上传,其键包含指定的前缀。

delimiter

字符串

前缀和对象名称其余部分之间的分隔符。

key-marker

字符串

上传列表的开头标记。

max-keys

整数

in-progress 上传的最大数量。默认值为 1000。

max-uploads

整数

多部分上传的最大数量。范围为 1 到 1000。默认值为 1000。

version-id-marker

字符串

如果没有指定 key-marker,则忽略。指定在 ID 或之后以字典顺序列出首次上传的 ID

表 2.18. 响应实体

名称类型描述

ListMultipartUploadsResult

Container

个用于结果的容器。

ListMultipartUploadsResult.Prefix

字符串

prefix 请求参数指定的前缀(若有)。

Bucket

字符串

将接收存储桶内容的 bucket。

KeyMarker

字符串

key-marker 请求参数指定的密钥标记(如果有)。

UploadIdMarker

字符串

upload-id-marker 请求参数指定的标记(若有)。

NextKeyMarker

字符串

如果 IsTruncatedtrue,则后续请求中使用的密钥标记。

NextUploadIdMarker

字符串

如果 IsTruncatedtrue,则后续请求中要使用的上传 ID 标记。

MaxUploads

整数

max-uploads 请求参数指定的最大上传数。

Delimiter

字符串

如果设置,具有相同前缀的对象将出现在 CommonPrefixes 列表中。

IsTruncated

布尔值

如果为 true,则只返回存储桶上传内容的子集。

Upload

Container

KeyUploadIdInitiatorOwner StorageClassInitiated 元素的容器。

Key

字符串

多部分上传完成后对象的密钥。

UploadId

字符串

标识多部分上传的 ID

Initiator

Container

包含启动上传的用户的 IDDisplayName

DisplayName

字符串

启动器的显示名称。

ID

字符串

启动器的 ID.

Owner

Container

拥有上传对象的用户的 IDDisplayName 的容器。

StorageClass

字符串

用于存储生成的对象的方法。STANDARD 或者 REDUCED_REDUNDANCY

Initiated

Date

用户开始上传的日期和时间。

CommonPrefixes

Container

如果多个对象包含相同的前缀,它们将显示在此列表中。

CommonPrefixes.Prefix

字符串

密钥在 prefix 请求参数定义的前缀后面的子字符串。

2.4.23. S3 bucket 策略

Ceph 对象网关支持应用于 bucket 的 Amazon S3 策略语言的子集。

创建和删除

Ceph 对象网关通过标准 S3 操作来管理 S3 Bucket 策略,而不使用 radosgw-admin CLI 工具。

管理员可以使用 s3cmd 命令设置或删除策略。

示例

$ cat > examplepol
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"AWS": ["arn:aws:iam::usfolks:user/fred"]},
    "Action": "s3:PutObjectAcl",
    "Resource": [
      "arn:aws:s3:::happybucket/*"
    ]
  }]
}

$ s3cmd setpolicy examplepol s3://happybucket
$ s3cmd delpolicy s3://happybucket

限制

Ceph 对象网关仅支持以下 S3 操作:

  • s3:AbortMultipartUpload
  • s3:CreateBucket
  • s3:DeleteBucketPolicy
  • s3:DeleteBucket
  • s3:DeleteBucketWebsite
  • s3:DeleteObject
  • s3:DeleteObjectVersion
  • s3:GetBucketAcl
  • s3:GetBucketCORS
  • s3:GetBucketLocation
  • s3:GetBucketPolicy
  • s3:GetBucketRequestPayment
  • s3:GetBucketVersioning
  • s3:GetBucketWebsite
  • s3:GetLifecycleConfiguration
  • s3:GetObjectAcl
  • s3:GetObject
  • s3:GetObjectTorrent
  • s3:GetObjectVersionAcl
  • s3:GetObjectVersion
  • s3:GetObjectVersionTorrent
  • s3:ListAllMyBuckets
  • s3:ListBucketMultiPartUploads
  • s3:ListBucket
  • s3:ListBucketVersions
  • s3:ListMultipartUploadParts
  • s3:PutBucketAcl
  • s3:PutBucketCORS
  • s3:PutBucketPolicy
  • s3:PutBucketRequestPayment
  • s3:PutBucketVersioning
  • s3:PutBucketWebsite
  • s3:PutLifecycleConfiguration
  • s3:PutObjectAcl
  • s3:PutObject
  • s3:PutObjectVersionAcl
注意

Ceph 对象网关不支持对用户、组或角色设置策略。

Ceph 对象网关使用 RGW"租户"标识符代替 Amazon 12 位帐户 ID。希望使用 Amazon Web Service(AWS)S3 和 Ceph 对象网关 S3 之间的策略的 Ceph 对象网关管理员必须在创建用户时使用 Amazon 帐户 ID 作为租户 ID。

使用 AWS S3 时,所有租户共享一个命名空间。相比之下,Ceph 对象网关为每个租户提供自己的 bucket 命名空间。目前,Ceph 对象网关客户端试图访问属于另一租户 MUST 的存储桶,在 S3 请求中将其作为 tenant:bucket 寻址。

在 AWS 中,bucket 策略可向其他帐户授予访问权限,该帐户所有者之后便可向具有用户权限的各个用户授予访问权限。由于 Ceph 对象网关尚不支持用户、角色和组权限,帐户所有者将需要直接向单个用户授予访问权限。

重要

授予整个帐户访问权限对存储桶将授予对该帐户中所有用户的访问权限。

bucket 策略 不支持 字符串插入。

Ceph 对象网关支持以下条件键:

  • aws:CurrentTime
  • aws:EpochTime
  • aws:PrincipalType
  • aws:Referer
  • aws:SecureTransport
  • aws:SourceIp
  • aws:UserAgent
  • aws:username

Ceph 对象 网关 ONLY 支持 ListBucket 操作的以下条件键:

  • s3:prefix
  • s3:delimiter
  • s3:max-keys

对 Swift 的影响

Ceph 对象网关不提供在 Swift API 下设置 bucket 策略的功能。不过,通过 S3 API 设置的 bucket 策略可管理 Swift 和 S3 操作。

Ceph 对象网关将 Swift 凭据与策略中指定的主体匹配。

2.4.24. S3 获取存储桶上的请求支付配置

使用 requestPayment 子资源返回存储桶的请求支付配置。用户需要是存储桶所有者,或者被授予存储桶上的 READ_ACP 权限。

在存储桶请求中添加 requestPayment 子资源,如下所示。

语法

GET /<bucket>?requestPayment HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

2.4.25. S3 在存储桶上设置请求支付配置

使用 requestPayment 子资源设置存储桶的请求支付配置。默认情况下,bucket 所有者为从存储桶下载付费。此配置参数使存储桶所有者能够指定请求下载的人员将收取请求费用并从存储桶中下载数据。

在存储桶请求中添加 requestPayment 子资源,如下所示。

语法

PUT /<bucket>?requestPayment HTTP/1.1
Host: cname.domain.com

表 2.19. 请求实体

名称类型描述

Payer

enum

指定谁支付下载和申请费用。

RequestPaymentConfiguration

Container

Payer 的容器。

2.4.26. 多租户存储桶操作

当客户端应用访问存储桶时,它总是使用特定用户的凭据来运行。在 storage-product} 集群中,每个用户都属于一个租户。因此,如果没有显式指定租户,每一存储桶操作在其上下文中都有一个隐式租户。因此,多租户与之前的版本完全向后兼容,只要引用用户的存储桶和引用用户属于同一租户。

扩展用于指定显式租户,这与所用的协议和身份验证系统不同。

在以下示例中,冒号分隔租户和 bucket。因此,一个示例 URL 是:

https://rgw.domain.com/tenant:bucket

相比之下,一个简单的 Python 示例在存储桶方法本身中分隔租户和存储桶:

示例

from boto.s3.connection import S3Connection, OrdinaryCallingFormat
  c = S3Connection(
    aws_access_key_id="TESTER",
    aws_secret_access_key="test123",
    host="rgw.domain.com",
    calling_format = OrdinaryCallingFormat()
  )
  bucket = c.get_bucket("tenant:bucket")

注意

使用多租户的 S3 风格子域不可能,因为主机名不能包含冒号或存储桶名称中尚未有效的任何其他分隔符。使用句点可创建模糊的语法。因此,bucket-in-URL-path 格式必须与多租户一起使用。

其它资源

2.4.27. 其它资源

2.5. S3 对象操作

作为开发人员,您可以通过 Ceph 对象网关使用 Amazon S3 应用程序编程接口(API)执行对象操作。

下表列出了对象的 Amazon S3 功能操作,以及功能的支持状态。

表 2.20. 对象操作

获取对象支持 

获取对象信息

支持

 

放置对象

支持

 

删除对象

支持

 

删除多个对象

支持

 

获取对象 ACL

支持

 

放置对象 ACL

支持

 

复制对象

支持

 

后对象

支持

 

选项对象

支持

 

启动多部分上传

支持

 

向多部分上传添加部分

支持

 

列出多部分上传的部分

支持

 

组合多部分上传

支持

 

复制多部分上传

支持

 

中止多部分上传

支持

 

multi-Tenancy

支持

 

2.5.1. 先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • RESTful 客户端。

2.5.2. S3 从存储桶获取对象

从存储桶检索对象:

语法

GET /BUCKET/OBJECT HTTP/1.1

添加 versionId 子资源以检索对象的特定版本:

语法

GET /BUCKET/OBJECT?versionId=VERSIONID HTTP/1.1

表 2.21. 请求标头

名称描述有效值必需

范围

要检索的对象范围。

范围:bytes=beginbyte-endbyte

if-modified-since

仅当自时间戳以来修改时才会被修改。

timestamp

if-unmodified-since

仅当自时间戳以来没有被修改时才会获得。

timestamp

if-match

仅在对象 ETag 与 ETag 匹配时才获取。

实体标签

if-none-match

仅在对象 ETag 与 ETag 匹配时才获取。

实体标签

表 2.22. 响应标头

名称描述

content-Range

数据范围只有在请求中指定了范围标头字段时才返回

x-amz-version-id

返回版本 ID 或 null。

2.5.3. S3 获取对象的信息

返回有关对象的信息。此请求将返回与 Get 对象请求相同的标头信息,但将仅包含元数据,而不包括对象数据有效负载。

检索对象的当前版本:

语法

HEAD /BUCKET/OBJECT HTTP/1.1

添加 versionId 子资源来检索特定版本的信息:

语法

HEAD /BUCKET/OBJECT?versionId=VERSIONID HTTP/1.1

表 2.23. 请求标头

名称描述有效值必需

范围

要检索的对象范围。

范围:bytes=beginbyte-endbyte

if-modified-since

仅当自时间戳以来修改时才会被修改。

timestamp

if-unmodified-since

仅当自时间戳以来没有被修改时才会获得。

timestamp

if-match

仅在对象 ETag 与 ETag 匹配时才获取。

实体标签

if-none-match

仅在对象 ETag 与 ETag 匹配时才获取。

实体标签

表 2.24. 响应标头

名称描述

x-amz-version-id

返回版本 ID 或 null。

2.5.4. S3 添加对象到存储桶

添加对象到存储桶。您必须对存储桶具有写入权限才能执行此操作。

语法

PUT /<bucket>/<object> HTTP/1.1

表 2.25. 请求标头

名称描述有效值必需

content-md5

消息的 base64 编码的 MD-5 哈希。

字符串无默认值或限制。

content-type

标准 MIME 类型。

任何 MIME 类型。默认: binary/octet-stream

x-amz-meta-<…​>

用户元数据.使用对象存储.

最多 8kb 的字符串。无默认值。

x-amz-acl

过时的 ACL.

private, public-read, public-read-write, authenticated-read

表 2.26. 响应标头

名称描述

x-amz-version-id

返回版本 ID 或 null。

2.5.5. S3 删除对象

删除对象。需要对包含的存储桶设置 WRITE 权限。

删除对象。如果对象版本控制为 on,它会创建一个标记。

语法

DELETE /BUCKET/OBJECT HTTP/1.1

要在版本控制时删除对象,您必须指定 versionId 子资源以及要删除的对象版本。

DELETE /BUCKET/OBJECT?versionId=versionID HTTP/1.1

2.5.6. S3 删除多个对象

此 API 调用从存储桶中删除多个对象。

语法

POST /<bucket>/<object>?delete HTTP/1.1

2.5.7. S3 获取对象的访问控制列表(ACL)

返回对象的当前版本的 ACL:

语法

GET /BUCKET/OBJECT?acl HTTP/1.1

添加 versionId 子资源以检索特定版本的 ACL:

语法

GET /BUCKET/OBJECT_versionId=_VERSIONID&acl HTTP/1.1

表 2.27. 响应标头

名称描述

x-amz-version-id

返回版本 ID 或 null。

表 2.28. 响应实体

名称类型描述

AccessControlPolicy

Container

用于响应的容器。

AccessControlList

Container

ACL 信息的容器。

Owner

Container

对象所有者 IDDisplayName 的容器。

ID

字符串

对象所有者的 ID。

DisplayName

字符串

对象所有者的显示名称。

Grant

Container

GranteePermission 的容器。

Grantee

Container

收到权限授权的用户 DisplayNameID 的容器。

Permission

字符串

授予 Grantee 对象的权限。

2.5.8. S3 设置对象的访问控制列表(ACL)

为对象的当前版本设置对象 ACL。

语法

PUT /BUCKET/OBJECT?acl

表 2.29. 请求实体

名称类型描述

AccessControlPolicy

Container

用于响应的容器。

AccessControlList

Container

ACL 信息的容器。

Owner

Container

对象所有者 IDDisplayName 的容器。

ID

字符串

对象所有者的 ID。

DisplayName

字符串

对象所有者的显示名称。

Grant

Container

GranteePermission 的容器。

Grantee

Container

收到权限授权的用户 DisplayNameID 的容器。

Permission

字符串

授予 Grantee 对象的权限。

2.5.9. S3 复制对象

要复制对象,请使用 PUT 并指定目标存储桶和对象名称。

语法

PUT /<dest_bucket>/<dest_object> HTTP/1.1
x-amz-copy-source: SOURCE_BUCKET/SOURCE_OBJECT

表 2.30. 请求标头

名称描述有效值必需

x-amz-copy-source

源存储桶名称 + 对象名称。

<bucket>/<object>

x-amz-acl

过时的 ACL.

private, public-read, public-read-write, authenticated-read

x-amz-copy-if-modified-since

仅在自时间戳以来修改时才复制。

timestamp

x-amz-copy-if-unmodified-since

仅当因为时间戳而未修改时,才复制。

timestamp

x-amz-copy-if-match

仅在对象 ETag 与 ETag 匹配时才复制。

实体标签

x-amz-copy-if-none-match

仅在对象 ETag 不匹配时才复制。

实体标签

表 2.31. 响应实体

名称类型描述

CopyObjectResult

Container

用于响应元素的容器。

LastModified

Date

源对象的最后修改日期。

ETag

字符串

新对象的 ETag。

其它资源

  • <additional resource 1>
  • <additional resource 2>

2.5.10. S3 使用 HTML 表单将对象添加到存储桶

使用 HTML 表单将对象添加到存储桶。您必须对存储桶具有写入权限才能执行此操作。

语法

POST /<bucket>/<object> HTTP/1.1

2.5.11. S3 确定请求的选项

用于确定能否通过特定来源、HTTP 方法和标头发送实际请求的 preflight 请求。

语法

OPTIONS /<object> HTTP/1.1

2.5.12. S3 启动多部分上传

启动多部分上传过程。返回 UploadId,您可以在添加其他部分、列出部分并完成或放弃多部分上传时指定它。

语法

POST /BUCKET/OBJECT?uploads

表 2.32. 请求标头

名称描述有效值必需

content-md5

消息的 base64 编码的 MD-5 哈希。

字符串无默认值或限制。

content-type

标准 MIME 类型。

任何 MIME 类型。默认: binary/octet-stream

x-amz-meta-<…​>

用户元数据.使用对象存储.

最多 8kb 的字符串。无默认值。

x-amz-acl

过时的 ACL.

private, public-read, public-read-write, authenticated-read

表 2.33. 响应实体

名称类型描述

InitiatedMultipartUploadsResult

Container

个用于结果的容器。

Bucket

字符串

将接收对象内容的 bucket。

Key

字符串

key 请求参数指定的键(如果有)。

UploadId

字符串

upload-id 请求参数指定的 ID,用于标识多部分上传(如果有)。

2.5.13. S3 添加部分到多部分上传

向多部分上传添加部分.

指定要在多部分上传中添加部分的 uploadId 子资源和上传 ID:

语法

PUT /BUCKET/OBJECT?partNumber=&uploadId=UPLOAD_ID HTTP/1.1

可能会返回以下 HTTP 响应:

表 2.34. HTTP 响应

HTTP 状态状态代码描述

404

NoSuchUpload

指定的 upload-id 与这个对象上的任何起始上传都不匹配

2.5.14. S3 列出多部分上传的部分

指定 uploadId 子资源和上传 ID 来列出多部分上传的部分:

语法

GET /BUCKET/OBJECT?uploadId=UPLOAD_ID HTTP/1.1

表 2.35. 响应实体

名称类型描述

InitiatedMultipartUploadsResult

Container

个用于结果的容器。

Bucket

字符串

将接收对象内容的 bucket。

Key

字符串

key 请求参数指定的键(如果有)。

UploadId

字符串

upload-id 请求参数指定的 ID,用于标识多部分上传(如果有)。

Initiator

Container

包含启动上传的用户的 IDDisplayName

ID

字符串

启动器的 ID.

DisplayName

字符串

启动器的显示名称。

Owner

Container

拥有上传对象的用户的 IDDisplayName 的容器。

StorageClass

字符串

用于存储生成的对象的方法。STANDARD 或者 REDUCED_REDUNDANCY

PartNumberMarker

字符串

如果 IsTruncatedtrue,则后续请求中使用的 part 标记。在列表前面.

NextPartNumberMarker

字符串

如果 IsTruncatedtrue,则后续请求中使用的下一部分标记。列表的末尾。

MaxParts

整数

max-parts 请求参数指定的响应中允许的最大部分。

IsTruncated

布尔值

如果为 true,则只返回对象的上传内容的子集。

Part

Container

KeyPartInitiatorOwner StorageClassInitiated 元素的容器。

PartNumber

整数

部分的标识号。

ETag

字符串

部分的实体标签.

Size

整数

上传的部分的大小。

2.5.15. S3 装配上传的组件

组合上传的部件并创建新对象,从而完成多部分上传。

指定 uploadId 子资源和上传 ID 以完成多部分上传:

语法

POST /BUCKET/OBJECT?uploadId= HTTP/1.1

表 2.36. 请求实体

名称类型描述必需

CompleteMultipartUpload

Container

由一个或多个部分组成的容器。

Part

Container

PartNumberETag 的容器。

PartNumber

整数

部分的标识符。

ETag

字符串

部分的实体标签.

表 2.37. 响应实体

名称类型描述

CompleteMultipartUploadResult

Container

用于响应的容器。

Location

URI

新对象的资源标识符(路径)。

Bucket

字符串

包含新对象的 bucket 的名称。

Key

字符串

对象的密钥。

ETag

字符串

新对象的实体标签。

2.5.16. S3 复制多部分上传

通过复制现有对象中的数据作为数据源上传部分。

指定 uploadId 子资源和上传 ID 来执行多部分上传副本:

语法

PUT /BUCKET/OBJECT?partNumber=PartNumber&uploadId=UploadId HTTP/1.1
Host: cname.domain.com

Authorization: AWS ACCESS_KEY:_HASH_OF_HEADER_AND_SECRET_

表 2.38. 请求标头

名称描述有效值必需

x-amz-copy-source

源存储桶名称和对象名称。

BUCKET/ 对象

x-amz-copy-source-range

从源对象复制的字节范围。

范围: bytes=first-last,其中第一个和最后一个是基于零字节的字节偏移来复制。例如: bytes=0-9 表示您要复制源的前十字节。

表 2.39. 响应实体

名称类型描述

CopyPartResult

Container

所有响应元素的容器。

ETag

字符串

返回新部分的 ETag。

LastModified

字符串

返回上次修改部分的日期。

.Additional Resources

2.5.17. S3 abort a multipart upload

中止多部分上传。

指定 uploadId 子资源和上传 ID 来中止多部分上传:

语法

DELETE /BUCKET/OBJECT?uploadId=UPLOAD_ID HTTP/1.1

2.5.18. S3 Hadoop 互操作性

对于需要 Hadoop 分布式文件系统(HDFS)访问的数据分析应用,可以使用 Apache S3A 连接器(Hadoop)访问 Ceph 对象网关。S3A 连接器是一种开源工具,可将 S3 兼容对象存储作为 HDFS 文件系统,在数据存储在 Ceph 对象网关中时读取和写入应用程序的语义。

Ceph 对象网关与带有 Hadoop 2.7.3 的 S3A 连接器完全兼容。

2.5.19. 其它资源

2.6. 其它资源

  • 请参阅 Amazon S3 通用请求标头 的附录 A
  • 请参阅 附录 B 以了解 Amazon S3 通用响应状态代码。
  • 有关不支持的标头字段,请参阅 附录 C

第 3 章 Ceph 对象网关和 Swift API

作为开发人员,您可以使用与 Swift API 数据访问模型兼容的 RESTful 应用编程接口(API)。您可以通过 Ceph 对象网关管理存储在红帽 Ceph 存储集群中的 bucket 和对象。

下表描述了当前 Swift 功能的支持状态:

表 3.1. 功能

功能Status丹麦语

身份验证

支持

 

获取帐户元数据

支持

没有自定义元数据

Swift ACL

支持

支持 Swift ACL 的子集

列出容器

支持

 

列出容器的对象

支持

 

创建容器

支持

 

删除容器

支持

 

获取容器元数据

支持

 

添加/更新容器元数据

支持

 

删除容器元数据

支持

 

获取对象

支持

 

创建/更新对象

支持

 

创建大型对象

支持

 

删除对象

支持

 

复制对象

支持

 

获取对象元数据

支持

 

添加/更新对象元数据

支持

 

Temp URL 操作

支持

 

CORS

不支持

 

使对象过期

支持

 

对象版本

不支持

 

静态网站

不支持

 

3.1. 先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • RESTful 客户端。

3.2. Swift API 限制

重要

以下限制应谨慎使用。您的硬件选择会有影响,因此您应该始终与您的红帽客户团队讨论这些要求。

  • 使用 Swift API 时的最大对象大小: 5GB
  • 使用 Swift API 时的最大元数据大小: 对可应用到对象的用户元数据总大小没有定义限制,但单个 HTTP 请求仅限于 16,000 字节。

3.3. 创建 Swift 用户

要测试 Swift 接口,请创建一个 Swift 子用户。创建 Swift 用户分为两个步骤:第一步是创建用户。第二步是创建机密密钥。

注意

在多站点部署中,始终在 master zone group 的 master zone 中的主机上创建用户。

先决条件

  • 安装 Ceph 对象网关.
  • Ceph 对象网关节点的根级别访问权限.

流程

  1. 创建 Swift 用户:

    语法

    radosgw-admin subuser create --uid=NAME --subuser=NAME:swift --access=full

    使用 Swift 用户名替换 NAME,例如:

    示例

    [root@rgw]# radosgw-admin subuser create --uid=testuser --subuser=testuser:swift --access=full
    {
        "user_id": "testuser",
        "display_name": "First User",
        "email": "",
        "suspended": 0,
        "max_buckets": 1000,
        "auid": 0,
        "subusers": [
            {
                "id": "testuser:swift",
                "permissions": "full-control"
            }
        ],
        "keys": [
            {
                "user": "testuser",
                "access_key": "O8JDE41XMI74O185EHKD",
                "secret_key": "i4Au2yxG5wtr1JK01mI8kjJPM93HNAoVWOSTdJd6"
            }
        ],
        "swift_keys": [
            {
                "user": "testuser:swift",
                "secret_key": "13TLtdEW7bCqgttQgPzxFxziu0AgabtOc6vM8DLA"
            }
        ],
        "caps": [],
        "op_mask": "read, write, delete",
        "default_placement": "",
        "placement_tags": [],
        "bucket_quota": {
            "enabled": false,
            "check_on_raw": false,
            "max_size": -1,
            "max_size_kb": 0,
            "max_objects": -1
        },
        "user_quota": {
            "enabled": false,
            "check_on_raw": false,
            "max_size": -1,
            "max_size_kb": 0,
            "max_objects": -1
        },
        "temp_url_keys": [],
        "type": "rgw"
    }

  2. 创建 secret 密钥:

    语法

    radosgw-admin key create --subuser=NAME:swift --key-type=swift --gen-secret

    使用 Swift 用户名替换 NAME,例如:

    示例

    [root@rgw]# radosgw-admin key create --subuser=testuser:swift --key-type=swift --gen-secret
    {
        "user_id": "testuser",
        "display_name": "First User",
        "email": "",
        "suspended": 0,
        "max_buckets": 1000,
        "auid": 0,
        "subusers": [
            {
                "id": "testuser:swift",
                "permissions": "full-control"
            }
        ],
        "keys": [
            {
                "user": "testuser",
                "access_key": "O8JDE41XMI74O185EHKD",
                "secret_key": "i4Au2yxG5wtr1JK01mI8kjJPM93HNAoVWOSTdJd6"
            }
        ],
        "swift_keys": [
            {
                "user": "testuser:swift",
                "secret_key": "a4ioT4jEP653CDcdU8p4OuhruwABBRZmyNUbnSSt"
            }
        ],
        "caps": [],
        "op_mask": "read, write, delete",
        "default_placement": "",
        "placement_tags": [],
        "bucket_quota": {
            "enabled": false,
            "check_on_raw": false,
            "max_size": -1,
            "max_size_kb": 0,
            "max_objects": -1
        },
        "user_quota": {
            "enabled": false,
            "check_on_raw": false,
            "max_size": -1,
            "max_size_kb": 0,
            "max_objects": -1
        },
        "temp_url_keys": [],
        "type": "rgw"
    }

3.4. Swift 验证用户

要验证用户,请在标头中创建一个包含 X-Auth-UserX-Auth-Key 的请求。

语法

GET /auth HTTP/1.1
Host: swift.example.com
X-Auth-User: johndoe
X-Auth-Key: R7UUOLFDI2ZI9PRCQ53K

Response 示例

HTTP/1.1 204 No Content
Date: Mon, 16 Jul 2012 11:05:33 GMT
Server: swift
X-Storage-Url: https://swift.example.com
X-Storage-Token: UOlCCC8TahFKlWuv9DB09TWHF0nDjpPElha0kAa
Content-Length: 0
Content-Type: text/plain; charset=UTF-8

注意

您可以通过在身份验证期间使用 X-Storage-Url 值执行 GET 请求,检索 Ceph Swift 兼容服务的数据。

其它资源

3.5. Swift 容器操作

作为开发人员,您可以通过 Ceph 对象网关使用 Swift 应用程序编程接口(API)执行容器操作。您可以列出、创建、更新和删除容器。您还可以添加或更新容器的元数据。

3.5.1. 先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • RESTful 客户端。

3.5.2. Swift 容器操作

容器是存储数据对象的一种机制。帐户可以有许多容器,但容器名称必须是唯一的。此 API 允许客户端创建容器,设置访问控制和元数据,检索容器的内容,以及删除容器。由于此 API 发出与特定用户帐户中信息相关的请求,因此此 API 中的所有请求都必须经过身份验证,除非容器的访问控制经过有意公开,即允许匿名请求。

注意

Amazon S3 API 使用术语"bucket"来描述数据容器。当您听说 Swift API 中的"bucket"时,术语"bucket"可能等同于术语 'container"。

对象存储的一个方面是不支持分层路径或目录。相反,它支持一个由一个或多个容器组成的级别,每个容器可能具有对象。RADOS 网关的 Swift 兼容 API 支持"伪堡-层次结构容器"概念,这是一种使用对象命名来模拟容器或目录层次结构的方法,而无需实际在存储系统中实施。您可以使用伪层次结构名称命名对象,如照片/构建/empire-state.jpg,但容器名称不能包含正斜杠(/)字符。

重要

将大型对象上传到版本控制的 Swift 容器时,请将 --leave-segments 选项与 python-swiftclient 实用程序一起使用。不使用 --leave-segments 覆盖清单文件。因此,一个现有的对象会被覆盖,这会导致数据丢失。

3.5.3. Swift 更新容器的访问控制列表(ACL)

当用户创建容器时,用户默认对容器具有读写访问权限。要允许其他用户读取容器的内容或写入容器,您必须特别启用该用户。您还可以在 X-Container-ReadX-Container-Write 设置中指定 *,以便有效地让所有用户从容器读取或写入容器。设置 * 使容器成为公共容器。这可让匿名用户从容器读取或写入容器。

语法

POST /AP_VERSION/ACCOUNT/TENANT:_CONTAINER_ HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN
X-Container-Read: *
X-Container-Write: UID1, UID2, UID3

表 3.2. 请求标头

名称描述类型必需

X-Container-Read

具有容器读取权限的用户 ID。

用户 ID 的逗号分隔字符串值。

X-Container-Write

具有容器写入权限的用户 ID。

用户 ID 的逗号分隔字符串值。

3.5.4. Swift 列出容器

指定 API 版本和帐户的 GET 请求将返回特定用户帐户的容器列表。由于请求返回特定用户的容器,因此请求需要身份验证令牌。无法匿名提交请求。

语法

GET /API_VERSION/ACCOUNT HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN

表 3.3. 请求参数

名称描述类型必需有效值

limit

将结果数限制为指定的值。

整数

不适用

format

定义结果的格式。

字符串

json 或者 xml

marker

返回大于标记值的结果列表。

字符串

不适用

响应中包含容器列表,或者返回 HTTP 204 响应代码

表 3.4. 响应实体

名称描述类型

account

帐户信息列表.

Container

container

容器列表。

Container

name

容器的名称。

字符串

bytes

容器的大小。

整数

3.5.5. Swift 列出容器的对象

要列出容器内的对象,请使用 API 版本、帐户和容器名称发出 GET 请求。您可以指定查询参数来过滤完整列表,或者退出参数以返回容器中存储的前 10,000 个对象名称的列表。

语法

GET /AP_VERSION/TENANT:_CONTAINER_ HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN

表 3.5. 参数

名称描述类型有效值必需

format

定义结果的格式。

字符串

json 或者 xml

prefix

将结果集限制为以指定前缀开头的对象。

字符串

不适用

marker

返回大于标记值的结果列表。

字符串

不适用

limit

将结果数限制为指定的值。

整数

0 - 10,000

delimiter

前缀和对象名称其余部分之间的分隔符。

字符串

不适用

path

对象的伪层次结构路径。

字符串

不适用

表 3.6. 响应实体

名称描述类型

container

容器.

Container

object

容器内的对象。

Container

name

容器内对象的名称。

字符串

hash

对象内容的哈希代码。

字符串

last_modified

对象内容的最后一次修改时间。

Date

content_type

对象中的内容类型。

字符串

3.5.6. Swift 创建容器

要创建新容器,请使用 API 版本、帐户和新容器名称发出 PUT 请求。容器名称必须是唯一的,不得包含正斜杠(/)字符,并且应小于 256 字节。您可以在请求中包含访问控制标头和元数据标头。您还可以包含存储策略,标识一组放置池的密钥。例如,执行 radosgw-admin zone get 查看 placement_pools 下的可用密钥列表。存储策略允许您为容器指定一组特殊的池,如基于 SSD 的存储。其操作是幂等的。如果您请求创建已存在的容器,它将返回 HTTP 202 返回代码,但不会创建另一个容器。

语法

PUT /AP_VERSION/ACCOUNT/TENANT:_CONTAINER_ HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN
X-Container-Read: COMMA_SEPARATED_UIDS
X-Container-Write: COMMA_SEPARATED_UIDS
X-Container-Meta-KEY:_VALUE_
X-Storage-Policy: PLACEMENT_POOLS_KEY

表 3.7. 标头

名称描述类型必需

X-Container-Read

具有容器读取权限的用户 ID。

用户 ID 的逗号分隔字符串值。

X-Container-Write

具有容器写入权限的用户 ID。

用户 ID 的逗号分隔字符串值。

X-Container-Meta-KEY

用户定义的元数据键,采用任意字符串值。

字符串

X-Storage-Policy

为 Ceph 对象网关在 placement_pools 下标识存储策略的密钥。为可用密钥执行 radosgw-admin zone get

字符串

如果已存在具有相同名称的容器,并且该用户是容器所有者,则操作将成功。否则操作将失败。

表 3.8. HTTP 响应

名称描述状态代码

409

容器已存在于其他用户的所有权下。

BucketAlreadyExists

3.5.7. Swift 删除容器

要删除容器,请使用 API 版本、帐户和容器名称发出 DELETE 请求。容器必须为空。如果要检查容器是否为空,对容器执行 HEAD 请求。成功删除容器后,您将能够重复使用容器名称。

语法

DELETE /AP_VERSION/ACCOUNT/TENANT:_CONTAINER_ HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN

表 3.9. HTTP 响应

名称描述状态代码

204

容器已被移除。

NoContent

3.5.8. Swift 添加或更新容器元数据

要向容器添加元数据,请使用 API 版本、帐户和容器名称发出 POST 请求。您必须对容器具有写入权限才能添加或更新元数据。

语法

POST /AP_VERSION/ACCOUNT/TENANT:_CONTAINER_ HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN
X-Container-Meta-Color: red
X-Container-Meta-Taste: salty

表 3.10. 请求标头

名称描述类型必需

X-Container-Meta-KEY

用户定义的元数据键,采用任意字符串值。

字符串

3.6. Swift 对象操作

作为开发人员,您可以通过 Ceph 对象网关使用 Swift 应用程序编程接口(API)执行对象操作。您可以列出、创建、更新和删除对象。您还可以添加或更新对象的元数据。

3.6.1. 先决条件

  • 正在运行的红帽 Ceph 存储群集.
  • RESTful 客户端。

3.6.2. Swift 对象操作

对象是用于存储数据和元数据的容器。容器可能有多个对象,但对象名称必须是唯一的。此 API 允许客户端创建对象、设置访问控制和元数据、检索对象的数据和元数据,以及删除对象。由于此 API 发出与特定用户帐户中信息相关的请求,因此此 API 中的所有请求都必须经过身份验证。除非容器或对象的访问控制有意公开访问,否则允许匿名请求。

3.6.3. Swift 获取对象

要检索对象,请使用 API 版本、帐户、容器和对象名称发出 GET 请求。您必须对容器具有读取权限,才能检索其中的对象。

语法

GET /AP_VERSION/ACCOUNT/TENANT:_CONTAINER_/OBJECT HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN

表 3.11. 请求标头

名称描述类型必需

range

若要检索对象内容的一个子集,您可以指定字节范围。

Date

If-Modified-Since

仅当修改源对象的 last_modified 属性的日期/时间后才会修改副本。

Date

If-Unmodified-Since

只有自源对象的 last_modified 属性的日期/时间以来未修改时,才复制。

Date

Copy-If-Match

只有请求中的 ETag 与源对象的 ETag 匹配时才复制。

ETag.

Copy-If-None-Match

只有请求中的 ETag 与源对象的 ETag 不匹配时才复制。

ETag.

表 3.12. 响应标头

名称描述

Content-Range

对象内容子集的范围。仅当请求中指定了范围标头字段时,才会返回。

3.6.4. Swift 创建或更新对象

要创建新对象,请使用 API 版本、帐户、容器名称和新对象的名称发出 PUT 请求。您必须对容器具有写入权限才能创建或更新对象。对象名称在容器内必须是唯一的。PUT 请求不是幂等的,因此如果您不使用唯一名称,请求将更新对象。但是,您可以在对象名称中使用伪层次结构语法,以将它与同一名称的另一个对象区分(如果它位于不同的伪层次结构目录下)。您可以在请求中包含访问控制标头和元数据标头。

语法

PUT /AP_VERSION/ACCOUNT/TENANT:_CONTAINER_ HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN

表 3.13. 请求标头

名称描述类型必需有效值

ETag

对象内容的 MD5 哈希。建议.

字符串

不适用

Content-Type

对象包含的内容类型。

字符串

不适用

Transfer-Encoding

指示对象是否为更大聚合对象的一部分。

字符串

chunked

3.6.5. Swift 删除对象

要删除对象,请使用 API 版本、帐户、容器和对象名称发出 DELETE 请求。您必须对容器具有写入权限才能删除其中的对象。成功删除对象后,您将能够重复使用对象名称。

语法

DELETE /API_VERSION/ACCOUNT/TENANT:_CONTAINER_/OBJECT HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN

3.6.6. Swift 复制对象

通过复制对象,您可以制作对象的服务器端副本,因此您不必下载对象并将其上传到另一个容器中。要将一个对象的内容复制到另一个对象,您可以使用 API 版本、帐户和容器名称发出 PUT 请求或 COPY 请求。

对于 PUT 请求,使用请求中的目标容器和对象名称,以及请求标头中的源容器和对象。

对于 Copy 请求,使用请求中的源容器和对象,以及请求标头中的目标容器和对象。您必须对容器具有写入权限才能复制对象。目标对象名称在容器内必须是唯一的。请求不是幂等的,因此如果您不使用唯一名称,请求将更新目的地对象。您可以在对象名称中使用伪层次结构语法,以区分目的地对象和同一名称的源对象(如果它位于不同的伪层次结构目录下)。您可以在请求中包含访问控制标头和元数据标头。

语法

PUT /AP_VERSION/ACCOUNT/TENANT:_CONTAINER_ HTTP/1.1
X-Copy-From: TENANT:_SOURCE_CONTAINER_/SOURCE_OBJECT
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN

或者:

语法

COPY /AP_VERSION/ACCOUNT/TENANT:_SOURCE_CONTAINER_/SOURCE_OBJECT HTTP/1.1
Destination: TENANT:DEST_CONTAINER_/DEST_OBJECT

表 3.14. 请求标头

名称描述类型必需

X-Copy-From

PUT 请求一起使用,用于定义源容器/对象路径。

字符串

是,如果使用 PUT

Destination

COPY 请求一起使用,用于定义目标容器/对象路径。

字符串

是,如果使用 COPY

If-Modified-Since

仅当修改源对象的 last_modified 属性的日期/时间后才会修改副本。

Date

If-Unmodified-Since

只有自源对象的 last_modified 属性的日期/时间以来未修改时,才复制。

Date

Copy-If-Match

只有请求中的 ETag 与源对象的 ETag 匹配时才复制。

ETag.

Copy-If-None-Match

只有请求中的 ETag 与源对象的 ETag 不匹配时才复制。

ETag.

3.6.7. Swift 获取对象元数据

要检索对象的元数据,请使用 API 版本、帐户、容器和对象名称发出 HEAD 请求。您必须对容器具有读取权限,才能从容器内的对象检索元数据。此请求返回与对象本身请求相同的标头信息,但不返回对象的数据。

语法

HEAD /AP_VERSION/ACCOUNT/TENANT:_CONTAINER_ /OBJECT HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN

3.6.8. Swift 添加或更新对象元数据

要向对象添加元数据,请使用 API 版本、帐户、容器和对象名称发出 POST 请求。您必须对父容器具有写入权限才能添加或更新元数据。

语法

POST /AP_VERSION/ACCOUNT/TENANT:_CONTAINER_/OBJECT HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN

表 3.15. 请求标头

名称描述类型必需

X-Object-Meta-KEY

用户定义的元数据键,采用任意字符串值。

字符串

3.7. Swift 临时 URL 操作

为了允许临时访问,Swift 端点支持 temp url 功能 radosgw。例如,GET 请求到不需要共享凭证的对象。

对于这个功能,最初应设置 X-Account-Meta-Temp-URL-KeyX-Account-Meta-Temp-URL-Key-2 的值。Temp URL 功能依赖于 HMAC-SHA1 签名来应对这些 secret 密钥。

3.7.1. Swift 获取临时 URL 对象

临时 URL 使用加密的 HMAC-SHA1 签名,包括以下元素:

  • Request 方法的值,即 "GET"(实例)
  • 到期时间,格式为自时期起的秒数,即 Unix 时间
  • 请求路径从"v1"开始

以上项目在规范化后会附加换行,并且使用 SHA-1 哈希算法针对之前发布的 Temp URL 键之一生成 HMAC。

下面提供了用于演示以上内容的 python 脚本示例:

示例

import hmac
from hashlib import sha1
from time import time

method = 'GET'
host = 'https://objectstore.example.com'
duration_in_seconds = 300  # Duration for which the url is valid
expires = int(time() + duration_in_seconds)
path = '/v1/your-bucket/your-object'
key = 'secret'
hmac_body = '%s\n%s\n%s' % (method, expires, path)
hmac_body = hmac.new(key, hmac_body, sha1).hexdigest()
sig = hmac.new(key, hmac_body, sha1).hexdigest()
rest_uri = "{host}{path}?temp_url_sig={sig}&temp_url_expires={expires}".format(
     host=host, path=path, sig=sig, expires=expires)
print rest_uri

输出示例

https://objectstore.example.com/v1/your-bucket/your-object?temp_url_sig=ff4657876227fc6025f04fcf1e82818266d022c6&temp_url_expires=1423200992

3.7.2. Swift POST 临时 URL 密钥

向带有所需 Key 的 swift 帐户的 POST 请求将为帐户设置 secret 临时 URL 密钥,以便为其提供对帐户的临时 URL 访问。支持最多两个密钥,并且会针对这两个密钥检查签名(如果存在),以便可以在不使临时 URL 无效的情况下轮转密钥。

语法

POST /API_VERSION/ACCOUNT HTTP/1.1
Host: FULLY_QUALIFIED_DOMAIN_NAME
X-Auth-Token: AUTH_TOKEN

表 3.16. 请求标头

名称描述类型必需

X-Account-Meta-Temp-URL-Key

采用任意字符串值的用户定义的键。

字符串

X-Account-Meta-Temp-URL-Key-2

采用任意字符串值的用户定义的键。

字符串

3.8. Swift 多租赁容器操作

当客户端应用访问容器时,它总是使用特定用户的凭据来运行。在红帽 Ceph 存储集群中,每个用户都属于一个租户。因此,如果没有显式指定租户,每个容器操作都会在其上下文中具有隐式租户。因此,多租户与之前的版本完全向后兼容,只要引用的容器和引用用户属于同一租户。

扩展用于指定显式租户,这与所用的协议和身份验证系统不同。

冒号分隔租户和容器,因此示例 URL 是:

示例

https://rgw.domain.com/tenant:container

相比之下,在 create_container() 方法中,只需在容器方法本身中分隔租户和容器:

示例

create_container("tenant:container")

3.9. 其它资源

附录 A. S3 通用请求标头

下表列出了有效的通用请求标头及其描述。

表 A.1. 请求标头

请求标头描述

CONTENT_LENGTH

请求正文的时长.

DATE

请求时间和日期(按 UTC)。

HOST

主机服务器的名称。

AUTHORIZATION

授权令牌.

附录 B. S3 通用响应状态代码

下表列出了有效的通用 HTTP 响应状态及其对应的代码。

表 B.1. 响应状态

HTTP 状态响应代码

100

继续

200

成功

201

Created

202

已接受

204

NoContent

206

部分内容

304

NotModified

400

InvalidArgument

400

InvalidDigest

400

BadDigest

400

InvalidBucketName

400

InvalidObjectName

400

UnresolvableGrantByEmailAddress

400

InvalidPart

400

InvalidPartOrder

400

RequestTimeout

400

EntityTooLarge

403

AccessDenied

403

UserSuspended

403

RequestTimeTooSkewed

404

NoSuchKey

404

NoSuchBucket

404

NoSuchUpload

405

MethodNotAllowed

408

RequestTimeout

409

BucketAlreadyExists

409

BucketNotEmpty

411

MissingContentLength

412

PreconditionFailed

416

InvalidRange

422

UnprocessableEntity

500

InternalError

附录 C. S3 不支持的标头字段

表 C.1. 不支持的标头字段

名称类型

x-amz-security-token

Request(请求)

server

响应

x-amz-delete-marker

响应

x-amz-id-2

响应

x-amz-request-id

响应

x-amz-version-id

响应

附录 D. Swift 请求标头

表 D.1. 请求标头

名称描述类型必需

X-Auth-User

要进行身份验证的关键 Ceph 对象网关用户名。

字符串

X-Auth-Key

与 Ceph 对象网关用户名关联的密钥。

字符串

附录 E. Swift 响应标头

服务器的响应应包含 X-Auth-Token 值。响应可能还包括 X-Storage-Url,它提供整个 API 文档中的其他请求中指定的 API_VERSION/ACCOUNT 前缀。

表 E.1. 响应标头

名称描述类型

X-Storage-Token

请求中指定的 X-Auth-User 的授权令牌。

字符串

X-Storage-Url

用户的 URL 和 API_VERSION/ACCOUNT 路径。

字符串

附录 F. 使用安全令牌服务 API 的示例

这些示例使用 Python 的 boto3 模块与 Ceph 对象网关实施安全令牌服务(STS)进行接口。在这些示例中,TESTER2 假定由 TESTER1 创建的角色,根据角色附加的权限策略访问 TESTER1 拥有的 S3 资源。

AssumeRole 示例创建一个角色,为角色分配策略,然后假定角色使用这些临时凭据获取临时凭据和 S3 资源访问权限。

AssumeRoleWithWebIdentity 示例使用 OpenID Connect 身份提供程序 Keycloak 的外部应用验证用户,以根据角色的权限策略获取临时凭据和 S3 资源。

AssumeRole 示例

import boto3

iam_client = boto3.client('iam',
aws_access_key_id=ACCESS_KEY_OF_TESTER1,
aws_secret_access_key=SECRET_KEY_OF_TESTER1,
endpoint_url=<IAM URL>,
region_name=''
)

policy_document = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"arn:aws:iam:::user/TESTER1\"]},\"Action\":[\"sts:AssumeRole\"]}]}"

role_response = iam_client.create_role(
AssumeRolePolicyDocument=policy_document,
Path='/',
RoleName='S3Access',
)

role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::*\"}}"

response = iam_client.put_role_policy(
RoleName='S3Access',
PolicyName='Policy1',
PolicyDocument=role_policy
)

sts_client = boto3.client('sts',
aws_access_key_id=ACCESS_KEY_OF_TESTER2,
aws_secret_access_key=SECRET_KEY_OF_TESTER2,
endpoint_url=<STS URL>,
region_name='',
)

response = sts_client.assume_role(
RoleArn=role_response['Role']['Arn'],
RoleSessionName='Bob',
DurationSeconds=3600
)

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=<S3 URL>,
region_name='',)

bucket_name = 'my-bucket'
s3bucket = s3client.create_bucket(Bucket=bucket_name)
resp = s3client.list_buckets()

AssumeRoleWithWebIdentity Example

import boto3

iam_client = boto3.client('iam',
aws_access_key_id=ACCESS_KEY_OF_TESTER1,
aws_secret_access_key=SECRET_KEY_OF_TESTER1,
endpoint_url=<IAM URL>,
region_name=''
)

policy_document = "{\"Version\":\"2012-10-17\",\"Statement\":\[\{\"Effect\":\"Allow\",\"Principal\":\{\"Federated\":\[\"arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/demo\"\]\},\"Action\":\[\"sts:AssumeRoleWithWebIdentity\"\],\"Condition\":\{\"StringEquals\":\{\"localhost:8080/auth/realms/demo:app_id\":\"customer-portal\"\}\}\}\]\}"
role_response = iam_client.create_role(
AssumeRolePolicyDocument=policy_document,
Path='/',
RoleName='S3Access',
)

role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::*\"}}"

response = iam_client.put_role_policy(
    RoleName='S3Access',
    PolicyName='Policy1',
    PolicyDocument=role_policy
)

sts_client = boto3.client('sts',
aws_access_key_id=ACCESS_KEY_OF_TESTER2,
aws_secret_access_key=SECRET_KEY_OF_TESTER2,
endpoint_url=<STS URL>,
region_name='',
)

response = client.assume_role_with_web_identity(
RoleArn=role_response['Role']['Arn'],
RoleSessionName='Bob',
DurationSeconds=3600,
WebIdentityToken=<Web Token>
)

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=<S3 URL>,
region_name='',)

bucket_name = 'my-bucket'
s3bucket = s3client.create_bucket(Bucket=bucket_name)
resp = s3client.list_buckets()

其它资源

  • 有关使用 Python 的 boto 模块的详情,请参阅红帽 Ceph 存储对象网关配置和管理指南中 的测试 S3 访问 部分。