golang实现S3存储GET/PUT/DELETE操作及OpenID/Basic认证的代理插件s3-proxy的使用
Golang实现S3存储GET/PUT/DELETE操作及OpenID/Basic认证的代理插件s3-proxy的使用
项目介绍
s3-proxy是一个用Go语言编写的S3存储代理服务,提供以下功能:
主要特性
- 多S3桶代理
- 索引文档支持
- 自定义模板
- 支持自定义S3端点
- Basic认证支持
- 多Basic认证支持
- OpenID Connect认证支持
- 多OpenID Connect提供者支持
- 通过主机名和路径支持桶挂载点配置
- 按路径和HTTP方法对每个桶进行认证
- Prometheus指标
- 允许在S3桶上发布文件
- 允许在S3桶上删除文件
使用示例
基本配置示例
# config.yaml 配置文件示例
log:
level: info
server:
port: 8080
# 可选的TLS配置
# tls:
# enabled: true
# certificate: /path/to/cert.pem
# privateKey: /path/to/key.pem
targets:
default:
bucket:
name: my-bucket
region: us-east-1
s3Endpoint: "" # 可选的自定义S3端点
credentials:
accessKey: "AWS_ACCESS_KEY_ID"
secretKey: "AWS_SECRET_ACCESS_KEY"
mount:
path: /
templates:
# 模板配置
认证配置示例
# 基本认证配置
authProviders:
basic:
users:
- username: "user1"
password: "$2a$10$n9OLVz..." # bcrypt哈希密码
- username: "user2"
password: "$2a$10$3f8Xb..."
# OpenID认证配置
authProviders:
oidc:
providers:
- name: google
clientID: "your-client-id"
clientSecret: "your-client-secret"
issuerURL: "https://accounts.google.com"
redirectURL: "http://your-domain.com/oauth2/callback"
scopes:
- "openid"
- "email"
- "profile"
Golang代码示例
package main
import (
"fmt"
"log"
"net/http"
"github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy"
)
func main() {
// 创建新的S3代理实例
proxy, err := s3proxy.New("config.yaml")
if err != nil {
log.Fatalf("Failed to create S3 proxy: %v", err)
}
// 启动HTTP服务器
server := &http.Server{
Addr: ":8080",
Handler: proxy.GetHTTPHandler(),
}
fmt.Println("Starting S3 proxy server on :8080")
if err := server.ListenAndServe(); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}
Docker部署示例
# 使用Docker运行s3-proxy
docker run -d \
-p 8080:8080 \
-v /path/to/config.yaml:/etc/s3-proxy/config.yaml \
oxynozeta/s3-proxy:latest
高级功能
桶操作API示例
// PUT操作示例 - 上传文件到S3
func uploadFile(w http.ResponseWriter, r *http.Request) {
// 从请求中获取文件
file, header, err := r.FormFile("file")
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
defer file.Close()
// 创建S3上传输入
input := &s3.PutObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String(header.Filename),
Body: file,
}
// 执行上传
_, err = s3Client.PutObject(input)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusCreated)
fmt.Fprintf(w, "Successfully uploaded %s", header.Filename)
}
// DELETE操作示例 - 从S3删除文件
func deleteFile(w http.ResponseWriter, r *http.Request) {
filename := r.URL.Query().Get("filename")
if filename == "" {
http.Error(w, "Filename is required", http.StatusBadRequest)
return
}
// 创建S3删除输入
input := &s3.DeleteObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String(filename),
}
// 执行删除
_, err := s3Client.DeleteObject(input)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "Successfully deleted %s", filename)
}
授权协议
Apache 2.0 (详见LICENSE文件)
更多关于golang实现S3存储GET/PUT/DELETE操作及OpenID/Basic认证的代理插件s3-proxy的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang实现S3存储GET/PUT/DELETE操作及OpenID/Basic认证的代理插件s3-proxy的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang实现S3存储操作及s3-proxy使用指南
S3基本操作实现
以下是使用Golang实现S3存储的GET/PUT/DELETE操作的示例代码:
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
// S3Client 封装S3操作
type S3Client struct {
client *s3.Client
bucket string
}
// NewS3Client 创建S3客户端
func NewS3Client(endpoint, region, bucket, accessKey, secretKey string) (*S3Client, error) {
customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
if endpoint != "" {
return aws.Endpoint{
URL: endpoint,
SigningRegion: region,
}, nil
}
return aws.Endpoint{}, &aws.EndpointNotFoundError{}
})
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithRegion(region),
config.WithEndpointResolverWithOptions(customResolver),
config.WithCredentialsProvider(aws.CredentialsProviderFunc(func(ctx context.Context) (aws.Credentials, error) {
return aws.Credentials{
AccessKeyID: accessKey,
SecretAccessKey: secretKey,
}, nil
})),
),
)
if err != nil {
return nil, fmt.Errorf("failed to load AWS config: %v", err)
}
client := s3.NewFromConfig(cfg)
return &S3Client{client: client, bucket: bucket}, nil
}
// PutObject 上传文件到S3
func (s *S3Client) PutObject(key string, filePath string) error {
file, err := os.Open(filePath)
if err != nil {
return fmt.Errorf("failed to open file: %v", err)
}
defer file.Close()
_, err = s.client.PutObject(context.TODO(), &s3.PutObjectInput{
Bucket: aws.String(s.bucket),
Key: aws.String(key),
Body: file,
})
if err != nil {
return fmt.Errorf("failed to put object: %v", err)
}
return nil
}
// GetObject 从S3下载文件
func (s *S3Client) GetObject(key string, filePath string) error {
result, err := s.client.GetObject(context.TODO(), &s3.GetObjectInput{
Bucket: aws.String(s.bucket),
Key: aws.String(key),
})
if err != nil {
return fmt.Errorf("failed to get object: %v", err)
}
defer result.Body.Close()
file, err := os.Create(filePath)
if err != nil {
return fmt.Errorf("failed to create file: %v", err)
}
defer file.Close()
_, err = io.Copy(file, result.Body)
if err != nil {
return fmt.Errorf("failed to write file: %v", err)
}
return nil
}
// DeleteObject 从S3删除文件
func (s *S3Client) DeleteObject(key string) error {
_, err := s.client.DeleteObject(context.TODO(), &s3.DeleteObjectInput{
Bucket: aws.String(s.bucket),
Key: aws.String(key),
})
if err != nil {
return fmt.Errorf("failed to delete object: %v", err)
}
return nil
}
func main() {
// 初始化S3客户端
client, err := NewS3Client(
"https://s3.example.com", // S3端点
"us-east-1", // 区域
"my-bucket", // 存储桶名称
"ACCESS_KEY", // 访问密钥
"SECRET_KEY", // 秘密密钥
)
if err != nil {
log.Fatal(err)
}
// 上传文件
err = client.PutObject("test.txt", "./test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("File uploaded successfully")
// 下载文件
err = client.GetObject("test.txt", "./downloaded.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("File downloaded successfully")
// 删除文件
err = client.DeleteObject("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("File deleted successfully")
}
s3-proxy使用指南
s3-proxy是一个开源的S3代理服务器,支持OpenID和Basic认证。以下是使用s3-proxy的步骤:
1. 安装s3-proxy
# 使用Docker安装
docker pull ghcr.io/oxyno-zeta/s3-proxy:latest
# 或者从源码编译
git clone https://github.com/oxyno-zeta/s3-proxy.git
cd s3-proxy
make build
2. 配置s3-proxy
创建配置文件config.yaml
:
# 监听配置
listen:
address: "0.0.0.0"
port: 8080
# S3目标配置
target:
bucket: "my-bucket"
endpoint: "https://s3.example.com"
region: "us-east-1"
credentials:
accessKey: "ACCESS_KEY"
secretKey: "SECRET_KEY"
# 认证配置
auth:
basic:
enabled: true
users:
- username: "admin"
password: "$2a$10$N9qo8uLOickgx2ZMRZoMy.Mrq4H9zLMHbJY3ZQ5yQ6eM3BvV7DfG." # bcrypt加密的密码
oidc:
enabled: true
issuerURL: "https://accounts.google.com"
clientID: "your-client-id"
clientSecret: "your-client-secret"
redirectURL: "http://localhost:8080/oauth2/callback"
scopes: ["openid", "email", "profile"]
# 模板配置
templates:
targetList:
enabled: true
path: "/"
notFound:
enabled: true
path: "/404"
3. 运行s3-proxy
# 使用Docker运行
docker run -d \
-p 8080:8080 \
-v $(pwd)/config.yaml:/etc/s3-proxy/config.yaml \
ghcr.io/oxyno-zeta/s3-proxy:latest
# 或者直接运行二进制
./s3-proxy --config ./config.yaml
4. 使用认证
Basic认证
curl -u admin:password http://localhost:8080/file.txt
OpenID认证
- 访问
http://localhost:8080
- 将被重定向到OpenID提供商登录页面
- 登录后将被重定向回s3-proxy
5. 高级配置
- 缓存控制: 可以配置缓存头
- CORS: 支持跨域资源共享配置
- HTTPS: 支持TLS配置
- 路径重写: 支持URL路径重写规则
# 高级配置示例
server:
tls:
enabled: true
cert: "/path/to/cert.pem"
key: "/path/to/key.pem"
cors:
enabled: true
allowedOrigins: ["*"]
allowedMethods: ["GET", "POST", "PUT", "DELETE"]
allowedHeaders: ["*"]
cache:
enabled: true
defaultMaxAge: 3600
总结
本文介绍了如何使用Golang实现S3的基本操作以及如何使用s3-proxy作为S3的代理服务器。s3-proxy提供了灵活的认证方式和丰富的配置选项,可以方便地集成到现有系统中。