管理认证请求

Amazon 的 S3 服务使用访问密钥以及请求头和密钥的散列来认证请求。 它具有在没有 SSL 开销的情况下提供已认证的请求 (尤其是大型上载) 的优点。

S3 API 的大多数用例都涉及使用开放式源代码 S3 客户机,例如 Amazon SDK for Java 或 Python Boto 中的 AmazonS3Client 。 这些库不支持 Ceph Object Gateway 管理 API。 您可以对这些库进行子类和扩展,以支持 Ceph 管理 API。 或者,您可以创建唯一的网关客户机。

创建 execute() 方法

本节中的示例类演示了如何创建一个xml-ph-0000@deepl.internal方法,该 CephAdminAPI 本节中的示例类演示了如何创建一个 execute() 方法,该方法可以接收请求参数、验证请求、调用Ceph Admin API并接收响应。

注: CephAdminAPI 类示例不受支持或不打算用于商业用途。 它仅用于说明目的。* *

调用 Ceph Object Gateway

客户机代码 包含对 Ceph Object Gateway 的五个调用,用于演示 CRUD 操作:

  • 创建用户

  • 获取用户

  • 修改用户

  • 创建子用户

  • 删除用户

以这个例子为例,获取 httpcomponents-client-4.5.3 Apache HTTP 组件。 你可以在这里下载: http://hc.apache.org/downloads.cgi。 然后解压缩 tar 文件,浏览至其 lib 目录,并将内容复制到 JAVA_HOME 目录的 /jre/lib/ext 目录或定制类路径。

当您查看 CephAdminAPI 类示例时,请注意, execute() 方法接受一个 HTTP 方法、一个请求路径、一个可选的子资源(如果未指定,则为 null )和一个参数映射。 要使用子资源 (例如, subuserkey) 执行,您将需要在 execute() 方法中指定子资源作为自变量。

示例方法:

  1. 构建 URI。

  2. 生成一个 HTTP 报头字符串。

  3. 例如, HTTP 请求的实例化, PUTPOSTGETDELETE

  4. Date 报头添加到 HTTP 报头字符串和请求报头中。

  5. 在 HTTP 请求头中添加 Authorization 头。

  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 来删除用户。

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

Authorization: AWS _ACCESS_KEY_:_HASH_OF_HEADER_AND_SECRET_

示例类有一个xml-ph-0000@deepl.internal方法,该方法接受标题字符串和管理员用户的密钥,并返回一个xml-ph-0001@deepl.internal H CephAdminAPI 示例类有一个 base64Sha1Hmac() 方法,该方法接受标题字符串和管理员用户的密钥,并返回一个 SHA1 HMAC作为 base-64 编码的字符串。 每个 execute() 调用都将调用同一代码行来构建 Authorization 头:

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

以下 CephAdminAPI 示例类要求您将访问密钥,密钥和端点传递给构造函数。 该类提供存取器方法以在运行时对其进行更改。

示例

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();
                }
        }
}