fix(supply-api): restore uncached build health
This commit is contained in:
@@ -2,6 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -12,7 +17,7 @@ import (
|
||||
|
||||
func TestMain_ProdStartupFailsWhenDatabaseUnavailable(t *testing.T) {
|
||||
configPath := filepath.Join(t.TempDir(), "config.prod.yaml")
|
||||
content := []byte(`
|
||||
content := []byte(fmt.Sprintf(`
|
||||
server:
|
||||
addr: "127.0.0.1:0"
|
||||
shutdown_timeout: 1s
|
||||
@@ -28,9 +33,10 @@ redis:
|
||||
port: 1
|
||||
token:
|
||||
issuer: "prod-issuer"
|
||||
secret_key: "prod-secret"
|
||||
algorithm: "HS256"
|
||||
`)
|
||||
algorithm: "RS256"
|
||||
public_key: |
|
||||
%s
|
||||
`, indentYAMLBlock(mustGenerateRSAPublicKeyPEM(t), " ")))
|
||||
if err := os.WriteFile(configPath, content, 0o600); err != nil {
|
||||
t.Fatalf("failed to write config file: %v", err)
|
||||
}
|
||||
@@ -88,3 +94,25 @@ func TestMainHelperProcess(t *testing.T) {
|
||||
main()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func mustGenerateRSAPublicKeyPEM(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to generate RSA key: %v", err)
|
||||
}
|
||||
der, err := x509.MarshalPKIXPublicKey(&privateKey.PublicKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal RSA public key: %v", err)
|
||||
}
|
||||
return string(pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: der}))
|
||||
}
|
||||
|
||||
func indentYAMLBlock(value, indent string) string {
|
||||
lines := strings.Split(strings.TrimRight(value, "\n"), "\n")
|
||||
for i, line := range lines {
|
||||
lines[i] = indent + line
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ token:
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFromPath_ProdRejectsMissingHS256SecretKey(t *testing.T) {
|
||||
func TestLoadFromPath_ProdRejectsHS256Algorithm(t *testing.T) {
|
||||
// 清除环境变量以确保测试隔离
|
||||
origVal := os.Getenv("SUPPLY_TOKEN_SECRET_KEY")
|
||||
os.Unsetenv("SUPPLY_TOKEN_SECRET_KEY")
|
||||
@@ -166,10 +166,10 @@ token:
|
||||
|
||||
_, err := LoadFromPath("prod", configPath)
|
||||
if err == nil {
|
||||
t.Fatal("expected prod config without HS256 secret key to return error")
|
||||
t.Fatal("expected prod config with HS256 algorithm to return error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "token.secret_key") {
|
||||
t.Fatalf("expected error to mention token.secret_key, got %v", err)
|
||||
if !strings.Contains(err.Error(), "token.algorithm") {
|
||||
t.Fatalf("expected error to mention token.algorithm, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"lijiaoqiao/supply-api/internal/pkg/pathutil"
|
||||
"lijiaoqiao/supply-api/internal/iam/service"
|
||||
"lijiaoqiao/supply-api/internal/middleware"
|
||||
|
||||
@@ -832,7 +833,7 @@ func TestExtractRoleCode(t *testing.T) {
|
||||
// func TestExtractRoleCodeFromUserPath(t *testing.T) { ... }
|
||||
|
||||
func TestSplitPath(t *testing.T) {
|
||||
result := splitPath("/api/v1/iam/roles/developer")
|
||||
result := pathutil.SplitPath("/api/v1/iam/roles/developer")
|
||||
assert.Equal(t, []string{"api", "v1", "iam", "roles", "developer"}, result)
|
||||
}
|
||||
|
||||
@@ -1267,4 +1268,3 @@ func TestToRoleResponse(t *testing.T) {
|
||||
assert.Equal(t, 20, response.Level)
|
||||
assert.True(t, response.IsActive)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Package pathutil provides path manipulation utilities.
|
||||
package pathutil
|
||||
|
||||
import "strings"
|
||||
|
||||
// SplitPath splits a URL or file path by '/' and returns non-empty segments.
|
||||
// Unlike strings.Split, this skips empty segments from leading/trailing/consecutive slashes.
|
||||
func SplitPath(path string) []string {
|
||||
|
||||
@@ -4,13 +4,14 @@ import (
|
||||
"context"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hkdf"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/hkdf"
|
||||
)
|
||||
|
||||
// ==================== P0-02 KMS加密方案 ====================
|
||||
@@ -207,7 +208,9 @@ func deriveDEK(keyID string, version int) []byte {
|
||||
ikm := append([]byte(keyID), byte(version&0xff))
|
||||
|
||||
hkdfReader := hkdf.New(sha256.New, ikm, nil, []byte("supply-api-dek-v1"))
|
||||
hkdfReader.Read(masterKey)
|
||||
if _, err := io.ReadFull(hkdfReader, masterKey); err != nil {
|
||||
panic(fmt.Sprintf("failed to derive DEK: %v", err))
|
||||
}
|
||||
return masterKey
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user