1// SPDX-License-Identifier: AGPL-3.0-or-later
2package config_test
3
4import (
5 "crypto/sha256"
6 "encoding/base64"
7 "os"
8 "path/filepath"
9 "strings"
10 "testing"
11
12 "bnema.dev/ermite/internal/config"
13 "github.com/stretchr/testify/assert"
14 "github.com/stretchr/testify/require"
15)
16
17func s3Env() map[string]string {
18 return map[string]string{
19 config.EnvS3Bucket: "bucket", config.EnvS3Region: "us-east-1",
20 config.EnvS3AccessKeyID: "private-id", config.EnvS3SecretAccessKey: "private-secret",
21 }
22}
23func TestStorageConfig(t *testing.T) {
24 c, err := config.Load(lookup(valid(nil)))
25 require.NoError(t, err)
26 assert.Empty(t, c.S3Bucket)
27 env := s3Env()
28 env[config.EnvS3Endpoint] = "http://localhost:9000/"
29 env[config.EnvS3Prefix] = "/forge/blobs/"
30 env[config.EnvS3ForcePathStyle] = "1"
31 env[config.EnvReleaseAssetMax] = "512MiB"
32 env[config.EnvReleaseQuota] = "10GiB"
33 env[config.EnvReleaseAssetsMax] = "7"
34 c, err = config.Load(lookup(valid(env)))
35 require.NoError(t, err)
36 assert.Equal(t, "forge/blobs/", c.S3Prefix)
37 assert.Equal(t, "http://localhost:9000", c.S3Endpoint)
38 assert.True(t, c.S3ForcePathStyle)
39 assert.EqualValues(t, 512<<20, c.ReleaseAssetMax)
40 assert.EqualValues(t, 10<<30, c.ReleaseQuota)
41 assert.Equal(t, 7, c.ReleaseAssetsMax)
42 for _, key := range []string{config.EnvS3Region, config.EnvS3AccessKeyID, config.EnvS3SecretAccessKey} {
43 t.Run(key, func(t *testing.T) {
44 env := s3Env()
45 env[key] = ""
46 _, err := config.Load(lookup(valid(env)))
47 require.Error(t, err)
48 assert.Contains(t, err.Error(), key)
49 assert.NotContains(t, err.Error(), "private-")
50 })
51 }
52 for key, value := range map[string]string{config.EnvS3Endpoint: "https://private-id:private-secret@example.org", config.EnvS3ForcePathStyle: "yes", config.EnvS3Prefix: "x/../y", config.EnvReleaseAssetMax: "0", config.EnvReleaseQuota: "-1", config.EnvReleaseAssetsMax: "0"} {
53 t.Run(key+" invalid", func(t *testing.T) {
54 env := s3Env()
55 env[key] = value
56 _, err := config.Load(lookup(valid(env)))
57 require.Error(t, err)
58 assert.Contains(t, err.Error(), key)
59 assert.NotContains(t, err.Error(), "private-")
60 })
61 }
62 for _, value := range []string{"0", "1", "false", "true"} {
63 env := s3Env()
64 env[config.EnvS3ForcePathStyle] = value
65 _, err := config.Load(lookup(valid(env)))
66 require.NoError(t, err)
67 }
68}
69func TestSecretFiles(t *testing.T) {
70 for _, key := range []string{config.EnvAdminToken, config.EnvSecretsKey, config.EnvS3AccessKeyID, config.EnvS3SecretAccessKey} {
71 t.Run(key, func(t *testing.T) {
72 secret := strings.Repeat("s", 32)
73 if key == config.EnvSecretsKey {
74 secret = base64.StdEncoding.EncodeToString([]byte(secret))
75 }
76 path := filepath.Join(t.TempDir(), "secret")
77 require.NoError(t, os.WriteFile(path, []byte(secret+"\r\n"), 0600))
78 env := valid(s3Env())
79 env[key] = ""
80 env[key+"_FILE"] = path
81 c, err := config.Load(lookup(env))
82 require.NoError(t, err)
83 switch key {
84 case config.EnvAdminToken:
85 assert.Equal(t, sha256.Sum256([]byte(secret)), c.AdminTokenHash)
86 case config.EnvSecretsKey:
87 assert.Len(t, c.SecretsKey, 32)
88 case config.EnvS3AccessKeyID:
89 assert.Equal(t, secret, c.S3AccessKeyID)
90 case config.EnvS3SecretAccessKey:
91 assert.Equal(t, secret, c.S3SecretAccessKey)
92 }
93 env[key] = secret
94 _, err = config.Load(lookup(env))
95 require.Error(t, err)
96 assert.Contains(t, err.Error(), "both")
97 assert.NotContains(t, err.Error(), secret)
98 env[key] = ""
99 env[key+"_FILE"] = path + "missing"
100 _, err = config.Load(lookup(env))
101 require.Error(t, err)
102 assert.Contains(t, err.Error(), key+"_FILE")
103 assert.NotContains(t, err.Error(), path)
104 require.NoError(t, os.WriteFile(path, []byte("\n"), 0600))
105 env[key+"_FILE"] = path
106 _, err = config.Load(lookup(env))
107 require.Error(t, err)
108 assert.Contains(t, err.Error(), "empty")
109 })
110 }
111}