golang实现S3存储GET/PUT/DELETE操作及OpenID/Basic认证的代理插件s3-proxy的使用

Golang实现S3存储GET/PUT/DELETE操作及OpenID/Basic认证的代理插件s3-proxy的使用

项目介绍

s3-proxy是一个用Go语言编写的S3存储代理服务,提供以下功能:

s3-proxy logo

主要特性

  • 多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认证

  1. 访问 http://localhost:8080
  2. 将被重定向到OpenID提供商登录页面
  3. 登录后将被重定向回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提供了灵活的认证方式和丰富的配置选项,可以方便地集成到现有系统中。

回到顶部