fix(storage): 共用 MinIO 实例下不再覆盖已存在桶的访问策略
deploy / deploy (push) Has been cancelled

MinIO 是多服务共用实例(sundynix-agent / sundynix-plant 等)。原先
ensureBucket 每次启动都无条件 SetBucketPolicy 设为公开只读,一旦
MINIO_BUCKET 配错成别的服务的桶,启动一次就会把人家的桶悄悄改成
全网可读且无任何报错。

改为:桶已存在则只连接、绝不修改策略并打日志说明;仅对本服务新建的
桶设公开只读(小程序需要图片直链)。.env.example 补充共用实例注意事项,
并建议改用仅授权 sundynix-pet 的独立账号替代 root 凭据。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-25 16:57:37 +08:00
parent eaa21585de
commit 8507d5060b
2 changed files with 21 additions and 5 deletions
+8
View File
@@ -12,6 +12,14 @@ MYSQL_PASSWORD=root
MYSQL_DATABASE=sundynix_pet
# ── 外部 MinIO(对象存储 / 图片) ──
# ⚠️ 这是多个服务共用的 MinIO 实例(sundynix-agent / sundynix-plant 等也在用):
# 1) BUCKET 必须填本项目自己的桶,填错别的服务的桶会污染人家数据;
# 2) 强烈建议不要用 root 凭据,另开一个只能访问 sundynix-pet 的账号:
# mc admin user add <alias> pets-svc <强密码>
# mc admin policy create <alias> pets-only pets-only.json # 只授权 sundynix-pet
# mc admin policy attach <alias> pets-only --user pets-svc
# 3) 桶已存在时程序不会修改其访问策略;图片直链需要该桶为 public-read
# 这一项由运维一次性配好。
# ENDPOINT 是「写入」用的 MinIO API 地址:内网直连、不带协议、不走 nginx。
# 公网等价地址是 162.14.122.200:3407(本机调试时可用,跨公网慢)。
MINIO_ENDPOINT=192.168.100.126:9000
+13 -5
View File
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"log"
"strings"
"time"
@@ -49,12 +50,18 @@ func (s *Storage) ensureBucket() error {
if err != nil {
return fmt.Errorf("bucket exists: %w", err)
}
if !exists {
if err := s.client.MakeBucket(ctx, s.bucket, minio.MakeBucketOptions{}); err != nil {
return fmt.Errorf("make bucket: %w", err)
}
if exists {
// 桶已存在:绝不碰它的策略。MinIO 可能是多个服务共用的,
// 万一 bucket 配错(填成别的服务的桶),无条件改策略会把人家的桶
// 悄悄变成全网可读。已存在的桶由运维一次性配好读权限。
log.Printf("minio: 复用已存在的 bucket %q(不修改其访问策略)", s.bucket)
return nil
}
// dev:设置公开只读策略,便于直接以 URL 访问对象
if err := s.client.MakeBucket(ctx, s.bucket, minio.MakeBucketOptions{}); err != nil {
return fmt.Errorf("make bucket: %w", err)
}
// 仅对「本服务刚创建」的桶设公开只读:小程序要用 URL 直接加载图片。
policy := fmt.Sprintf(`{
"Version": "2012-10-17",
"Statement": [{
@@ -67,6 +74,7 @@ func (s *Storage) ensureBucket() error {
if err := s.client.SetBucketPolicy(ctx, s.bucket, policy); err != nil {
return fmt.Errorf("set bucket policy: %w", err)
}
log.Printf("minio: 已创建 bucket %q 并设为公开只读(图片需可直链访问)", s.bucket)
return nil
}