这段 Go 代码是用于创建 Ceph 用户并获取其 S3 访问密钥的示例。已经过实际应用可以直接拿来使用
、
导入的包
Go
import (
"crypto/hmac"
"crypto/sha1"
"encoding/json"
"net/http"
"net/url"
"fmt"
"io"
"time"
"errors"
"encoding/base64"
)
这些包提供了加密、网络请求、时间处理、输入输出等功能,是实现本功能所必需的。
辅助函数:makeHMac
Go
func makeHMac(key []byte, data []byte) []byte {
hash := hmac.New(sha1.New, key)
hash.Write(data)
return hash.Sum(nil)
}
这个函数用于生成 HMAC(Hash-based Message Authentication Code),这是一种用于消息认证的安全码,可以防止信息被篡改。
数据结构定义
Go
type Response struct {
Keys []Credentials `json:"keys"`
}
type Credentials struct {
AccessKey string `json:"access_key"`
SecretKey string `json:"secret_key"`
User string `json:"user"`
}
Response 和 Credentials 结构体用于解析从 Ceph 返回的 JSON 数据。这些数据包含了用户的访问密钥和密钥。
主函数:CreateCephUser
Go
func CreateCephUser(uid, display, email, accessKey, secretKey string) (s3key, secret string, err error) {
...
}
这个函数接受用户 ID、显示名、电子邮件地址以及可选的访问密钥和密钥,返回新创建的 S3 访问密钥和密钥。
构建请求 URL
Go
baseURL := "http://192.168.1.224:80/admin/user?format=json"
u, err := url.Parse(baseURL)
...
queryParams := url.Values{}
...
u.RawQuery = queryParams.Encode()
这部分代码构建了一个 HTTP 请求的 URL,包括必要的查询参数。
创建和发送 HTTP 请求
Go
req, err := http.NewRequest("PUT", u.String(), nil)
...
signature := makeHMac([]byte(cephConn.Secret), []byte(strToSign))
...
resp, err := client.Do(req)
这里创建了一个 HTTP PUT 请求,用于向 Ceph 发送创建用户的命令。请求中包含了通过 HMAC 签名的授权头,确保请求的安全性。
处理响应
Go
bodyBytes, err := io.ReadAll(resp.Body)
...
var response Response
if err := json.Unmarshal(bodyBytes, &response); err != nil {
...
}
完整代码如下:
Go
package ceph
import (
"crypto/hmac"
"crypto/sha1"
"encoding/json"
"net/http"
"net/url"
"fmt"
"io"
"time"
"errors"
"encoding/base64"
)
func makeHMac(key []byte, data []byte) []byte {
hash := hmac.New(sha1.New, key)
hash.Write(data)
return hash.Sum(nil)
}
type Response struct {
Keys []Credentials `json:"keys"`
}
type Credentials struct {
AccessKey string `json:"access_key"`
SecretKey string `json:"secret_key"`
User string `json:"user"`
}
func CreateCephUser(uid, display, email, accessKey, secretKey string) (s3key, secret string, err error){
// session = GetCephAdminConn()
client := &http.Client{}
//url
baseURL := "http://192.168.1.224:80/admin/user?format=json"
// 创建 URL 对象
u, err := url.Parse(baseURL)
if err != nil {
//.GetLogger().Errorf("Error parsing base URL: %v", err)
return "", "", err
}
// 创建 URL 查询参数
queryParams := url.Values{}
queryParams.Add("uid", uid)
queryParams.Add("display-name", display)
queryParams.Add("email", email)
queryParams.Add("user-caps", "usage=read;users=read;buckets=read,write;metadata=read")
if accessKey != "" && secretKey != "" {
queryParams.Add("access-key", accessKey)
queryParams.Add("secret-key", secretKey)
}
// 将查询参数添加到 URL
u.RawQuery = queryParams.Encode()
// 创建请求
req, err := http.NewRequest("PUT", u.String(), nil)
if err != nil {
//.GetLogger().Errorf("Error creating request: %v", err)
return "", "", err
}
// 生成签名
utcTime := time.Now().UTC()
timestamp := utcTime.Format("Mon, 2 Jan 2006 15:04:05") + " +0000"
strToSign := "PUT\n\n\n" + timestamp + "\n/admin/user"
signature := makeHMac([]byte(cephConn.Secret), []byte(strToSign))
req.Header.Add("Date", timestamp)
req.Header.Add("Authorization", "AWS "+cephConn.S3key+":"+base64.StdEncoding.EncodeToString(signature))
resp, err := client.Do(req)
if err != nil {
//your_logger_package.GetLogger().Errorf("Error sending request: %v", err)
return "", "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
//bodyBytes, _ := io.ReadAll(resp.Body)
//your_logger_package.GetLogger().Warnf("Request not ok with status: %d, body: %s", resp.StatusCode, string(bodyBytes))
return "", "", fmt.Errorf("request failed with status: %d", resp.StatusCode)
}
// 读取响应体内容
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
//your_logger_package.GetLogger().Errorf("Error reading response body: %v", err)
return "", "", err
}
// 解析响应内容
var response Response
if err := json.Unmarshal(bodyBytes, &response); err != nil {
//your_logger_package.GetLogger().Errorf("Error parsing response: %v", err)
return "", "", err
}
if len(response.Keys) > 0 {
s3key = response.Keys[0].AccessKey
secret = response.Keys[0].SecretKey
} else {
return "", "", errors.New("no keys found in the response")
}
return s3key, secret, nil
}
由此我们可以衍生出对ceph的上传,下载,删除等功能函数,如下:
Go
func (session *StorageSession) UploadObject(objectKey string, content []byte) error
func (session *StorageSession) DeleteObject(key string) error
func (session *StorageSession) DownloadObject(objectKey string)
完整的函数实现放在网盘了,自取:https://pan.quark.cn/s/d0a005cfb3ae