go语言调用s3接口通过rgw节点创建ceph用户

这段 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

相关推荐
李歘歘3 小时前
Redis数据库——Redis雪崩、穿透、击穿
java·数据库·redis·mysql·缓存·go
探索云原生6 小时前
使用 NodeLocalDNS 提升集群 DNS 性能和可靠性
linux·docker·云原生·kubernetes·go·dns
2401_871213309 小时前
ceph文件系统
ceph
菠菠萝宝13 小时前
【Go学习】-01-5-网络编程
网络·学习·http·golang·go·网络编程·tcp
qq_448941082 天前
ceph文件系统
ceph
土豆凌凌七2 天前
GO:复用对象和协程资源
go·协程·对象池·协程池
Al_WAYS7783 天前
搭建开源版Ceph分布式存储
ceph
Pandaconda3 天前
【Golang 面试题】每日 3 题(十三)
开发语言·笔记·后端·面试·职场和发展·golang·go
沉默的八哥4 天前
Ceph对象存储接口的路线
ceph