fix: separate public object store TLS

This commit is contained in:
Codex Local
2026-08-26 10:26:06 +08:00
parent 42e7a82dad
commit f3dc6deb2e
9 changed files with 40 additions and 20 deletions
+1 -1
View File
@@ -80,7 +80,7 @@ func Run(ctx context.Context, serviceName string) error {
if err != nil {
return fmt.Errorf("create memory embedding provider: %w", err)
}
exportStore, err = objectstore.New(cfg.ObjectStoreEndpoint, cfg.ObjectStorePublic, cfg.ObjectStoreAccessKey, cfg.ObjectStoreSecretKey, cfg.ObjectStoreBucket, cfg.ObjectStoreRegion, cfg.ObjectStoreSecure)
exportStore, err = objectstore.New(cfg.ObjectStoreEndpoint, cfg.ObjectStorePublic, cfg.ObjectStoreAccessKey, cfg.ObjectStoreSecretKey, cfg.ObjectStoreBucket, cfg.ObjectStoreRegion, cfg.ObjectStoreSecure, cfg.ObjectStorePublicSecure)
if err != nil {
return fmt.Errorf("create private export object store: %w", err)
}
+7 -1
View File
@@ -86,6 +86,7 @@ type Config struct {
ObjectStoreBucket string
ObjectStoreRegion string
ObjectStoreSecure bool
ObjectStorePublicSecure bool
ExportDownloadTTL time.Duration
ExportObjectTTL time.Duration
MediaLocalDeleteGrace time.Duration
@@ -195,6 +196,10 @@ func Load(serviceName string) (Config, error) {
if err != nil {
return Config{}, err
}
objectStorePublicSecure, err := boolEnv("OBJECT_STORE_PUBLIC_SECURE", objectStoreSecure)
if err != nil {
return Config{}, err
}
environment := stringEnv("APP_ENV", EnvironmentLocal)
secretValues, err := loadSecretValues(
"DATABASE_URL", "REDIS_PASSWORD", "DEVICE_LOCAL_SECRET", "RTC_APP_KEY", "RTC_TOKEN_SIGNING_SECRET",
@@ -304,6 +309,7 @@ func Load(serviceName string) (Config, error) {
ObjectStoreBucket: objectStoreBucket,
ObjectStoreRegion: objectStoreRegion,
ObjectStoreSecure: objectStoreSecure,
ObjectStorePublicSecure: objectStorePublicSecure,
ExportDownloadTTL: exportDownloadTTL,
ExportObjectTTL: exportObjectTTL,
MediaLocalDeleteGrace: mediaLocalDeleteGrace,
@@ -590,7 +596,7 @@ func (c Config) validateProduction() error {
}
}
if c.ServiceName == "api" || c.ServiceName == "worker" {
if !c.ObjectStoreSecure {
if !c.ObjectStoreSecure || !c.ObjectStorePublicSecure {
return errors.New("production object storage must use TLS")
}
if isLocalValue(c.ObjectStoreEndpoint) || isLocalValue(c.ObjectStorePublic) {
+3
View File
@@ -118,6 +118,7 @@ func TestProductionAPIAcceptsHardenedConfiguration(t *testing.T) {
cfg.ObjectStoreAccessKey = strings.Repeat("a", 40)
cfg.ObjectStoreSecretKey = strings.Repeat("s", 40)
cfg.ObjectStoreSecure = true
cfg.ObjectStorePublicSecure = true
cfg.EmbeddingProvider = "ark"
cfg.ArkBaseURL = "https://ark.cn-beijing.volces.com/api/v3"
cfg.ArkAPIKey = strings.Repeat("k", 40)
@@ -150,6 +151,7 @@ func TestProductionRejectsReusedSigningSecrets(t *testing.T) {
cfg.ObjectStoreAccessKey = strings.Repeat("a", 40)
cfg.ObjectStoreSecretKey = strings.Repeat("s", 40)
cfg.ObjectStoreSecure = true
cfg.ObjectStorePublicSecure = true
cfg.EmbeddingProvider = "ark"
cfg.ArkBaseURL = "https://ark.cn-beijing.volces.com/api/v3"
cfg.ArkAPIKey = strings.Repeat("k", 40)
@@ -182,6 +184,7 @@ func TestProductionWorkerRequiresRealArkContentGenerator(t *testing.T) {
cfg.ObjectStoreAccessKey = strings.Repeat("a", 40)
cfg.ObjectStoreSecretKey = strings.Repeat("s", 40)
cfg.ObjectStoreSecure = true
cfg.ObjectStorePublicSecure = true
if err = cfg.Validate(); err == nil || !strings.Contains(err.Error(), "content generation") {
t.Fatalf("Validate() error=%v, want local content generator production gate", err)
}
+5 -4
View File
@@ -26,16 +26,17 @@ type Store struct {
bucket string
}
func New(endpoint, publicEndpoint, accessKey, secretKey, bucket, region string, secure bool) (*Store, error) {
func New(endpoint, publicEndpoint, accessKey, secretKey, bucket, region string, secure, publicSecure bool) (*Store, error) {
if endpoint == "" || publicEndpoint == "" || accessKey == "" || secretKey == "" || bucket == "" || region == "" {
return nil, errors.New("object store endpoints, credentials, bucket and region are required")
}
options := &minio.Options{Creds: credentials.NewStaticV4(accessKey, secretKey, ""), Secure: secure, Region: region}
internalClient, err := minio.New(endpoint, options)
internalOptions := &minio.Options{Creds: credentials.NewStaticV4(accessKey, secretKey, ""), Secure: secure, Region: region}
internalClient, err := minio.New(endpoint, internalOptions)
if err != nil {
return nil, fmt.Errorf("create internal object store client: %w", err)
}
publicClient, err := minio.New(publicEndpoint, options)
publicOptions := &minio.Options{Creds: credentials.NewStaticV4(accessKey, secretKey, ""), Secure: publicSecure, Region: region}
publicClient, err := minio.New(publicEndpoint, publicOptions)
if err != nil {
return nil, fmt.Errorf("create public object store signer: %w", err)
}
+4 -4
View File
@@ -15,10 +15,10 @@ import (
)
func TestStoreValidationAndOfflineSigning(t *testing.T) {
if _, err := New("", "localhost:59000", "key", "secret", "bucket", "us-east-1", false); err == nil {
if _, err := New("", "localhost:59000", "key", "secret", "bucket", "us-east-1", false, false); err == nil {
t.Fatal("missing internal endpoint was accepted")
}
store, err := New("localhost:59000", "localhost:59000", "local_minio", "local_minio_password", "private-exports", "us-east-1", false)
store, err := New("localhost:59000", "localhost:59000", "local_minio", "local_minio_password", "private-exports", "us-east-1", false, true)
if err != nil {
t.Fatal(err)
}
@@ -31,7 +31,7 @@ func TestStoreValidationAndOfflineSigning(t *testing.T) {
t.Fatal(err)
}
parsed, err := url.Parse(download)
if err != nil || parsed.Query().Get("X-Amz-Signature") == "" || parsed.Query().Get("response-content-disposition") != `attachment; filename="export.json"` {
if err != nil || parsed.Scheme != "https" || parsed.Query().Get("X-Amz-Signature") == "" || parsed.Query().Get("response-content-disposition") != `attachment; filename="export.json"` {
t.Fatalf("download URL=%q parsed=%+v err=%v", download, parsed, err)
}
if _, err := store.PresignUpload(ctx, "synthetic/firmware.bin", 0); err == nil {
@@ -65,7 +65,7 @@ func TestStoreMinIOObjectLifecycle(t *testing.T) {
if endpoint == "" {
t.Skip("TEST_OBJECT_STORE_ENDPOINT is not set")
}
store, err := New(endpoint, endpoint, "local_minio", "local_minio_password", "private-exports", "us-east-1", false)
store, err := New(endpoint, endpoint, "local_minio", "local_minio_password", "private-exports", "us-east-1", false, false)
if err != nil {
t.Fatal(err)
}