v3.4.1 de8f68e

public_tls_resolver_test.go RawHistoryFolder

1package secrets
2
3import (
4	"context"
5	"errors"
6	"os"
7	"path/filepath"
8	"testing"
9
10	"github.com/stretchr/testify/assert"
11	"github.com/stretchr/testify/require"
12
13	"github.com/bnema/gordon/internal/boundaries/out"
14	"github.com/bnema/gordon/internal/domain"
15)
16
17func TestPublicTLSResolverPrefersPass(t *testing.T) {
18	env := map[string]string{
19		"GORDON_CLOUDFLARE_API_TOKEN": "env-token",
20	}
21	resolver := NewPublicTLSResolver(PublicTLSResolverConfig{
22		PassLookup: func(_ context.Context, _ string) (string, error) {
23			return " pass-token\n", nil
24		},
25		EnvLookup: func(key string) string {
26			return env[key]
27		},
28	})
29
30	sv, err := resolver.ResolveCloudflareToken(context.Background())
31	require.NoError(t, err)
32	assert.Equal(t, "pass-token", sv.Value)
33	assert.Equal(t, domain.ACMETokenSourcePass, sv.Source)
34}
35
36func TestPublicTLSResolverFallsBackToTokenFile(t *testing.T) {
37	tmpDir := t.TempDir()
38	tmpFile := filepath.Join(tmpDir, "cf-token")
39	err := os.WriteFile(tmpFile, []byte("file-token\n"), 0644)
40	require.NoError(t, err)
41
42	env := map[string]string{
43		"GORDON_CLOUDFLARE_API_TOKEN_FILE": tmpFile,
44	}
45	resolver := NewPublicTLSResolver(PublicTLSResolverConfig{
46		PassLookup: func(_ context.Context, _ string) (string, error) {
47			return "", os.ErrNotExist
48		},
49		EnvLookup: func(key string) string {
50			return env[key]
51		},
52	})
53
54	sv, err := resolver.ResolveCloudflareToken(context.Background())
55	require.NoError(t, err)
56	assert.Equal(t, "file-token", sv.Value)
57	assert.Equal(t, domain.ACMETokenSourceFile, sv.Source)
58}
59
60func TestPublicTLSResolverFallsBackToEnv(t *testing.T) {
61	env := map[string]string{
62		"GORDON_CLOUDFLARE_API_TOKEN": "env-token",
63	}
64	resolver := NewPublicTLSResolver(PublicTLSResolverConfig{
65		PassLookup: func(_ context.Context, _ string) (string, error) {
66			return "", os.ErrNotExist
67		},
68		EnvLookup: func(key string) string {
69			return env[key]
70		},
71	})
72
73	sv, err := resolver.ResolveCloudflareToken(context.Background())
74	require.NoError(t, err)
75	assert.Equal(t, "env-token", sv.Value)
76	assert.Equal(t, domain.ACMETokenSourceEnv, sv.Source)
77}
78
79func TestPublicTLSResolverNoToken(t *testing.T) {
80	env := map[string]string{}
81	resolver := NewPublicTLSResolver(PublicTLSResolverConfig{
82		PassLookup: func(_ context.Context, _ string) (string, error) {
83			return "", os.ErrNotExist
84		},
85		EnvLookup: func(key string) string {
86			return env[key]
87		},
88	})
89
90	sv, err := resolver.ResolveCloudflareToken(context.Background())
91	require.NoError(t, err)
92	assert.Empty(t, sv.Value)
93	assert.Equal(t, domain.ACMETokenSourceNone, sv.Source)
94}
95
96func TestPublicTLSResolverPassErrorWithoutFallback(t *testing.T) {
97	expectedErr := errors.New("pass show failed")
98	resolver := NewPublicTLSResolver(PublicTLSResolverConfig{
99		PassLookup: func(_ context.Context, _ string) (string, error) {
100			return "", expectedErr
101		},
102		EnvLookup: func(key string) string {
103			return ""
104		},
105	})
106
107	sv, err := resolver.ResolveCloudflareToken(context.Background())
108	require.Error(t, err)
109	assert.Contains(t, err.Error(), "resolve pass token")
110	assert.Contains(t, err.Error(), expectedErr.Error())
111	assert.Empty(t, sv.Value)
112	assert.Equal(t, domain.ACMETokenSourceNone, sv.Source)
113}
114
115func TestPublicTLSResolverPassErrorWithEnvFallback(t *testing.T) {
116	resolver := NewPublicTLSResolver(PublicTLSResolverConfig{
117		PassLookup: func(_ context.Context, _ string) (string, error) {
118			return "", errors.New("pass not available")
119		},
120		EnvLookup: func(key string) string {
121			if key == "GORDON_CLOUDFLARE_API_TOKEN" {
122				return "env-token"
123			}
124			return ""
125		},
126	})
127
128	sv, err := resolver.ResolveCloudflareToken(context.Background())
129	require.NoError(t, err)
130	assert.Equal(t, "env-token", sv.Value)
131	assert.Equal(t, domain.ACMETokenSourceEnv, sv.Source)
132}
133
134func TestPublicTLSResolverTokenFileErrorWithoutFallback(t *testing.T) {
135	resolver := NewPublicTLSResolver(PublicTLSResolverConfig{
136		PassLookup: func(_ context.Context, _ string) (string, error) {
137			return "", os.ErrNotExist
138		},
139		EnvLookup: func(key string) string {
140			if key == "GORDON_CLOUDFLARE_API_TOKEN_FILE" {
141				return "/nonexistent/token-file"
142			}
143			return ""
144		},
145	})
146
147	sv, err := resolver.ResolveCloudflareToken(context.Background())
148	require.Error(t, err)
149	assert.Contains(t, err.Error(), "read token file")
150	assert.Empty(t, sv.Value)
151	assert.Equal(t, domain.ACMETokenSourceNone, sv.Source)
152}
153
154func TestPublicTLSResolverTokenFileErrorWithEnvFallback(t *testing.T) {
155	resolver := NewPublicTLSResolver(PublicTLSResolverConfig{
156		PassLookup: func(_ context.Context, _ string) (string, error) {
157			return "", os.ErrNotExist
158		},
159		EnvLookup: func(key string) string {
160			if key == "GORDON_CLOUDFLARE_API_TOKEN_FILE" {
161				return "/nonexistent/token-file"
162			}
163			if key == "GORDON_CLOUDFLARE_API_TOKEN" {
164				return "env-token"
165			}
166			return ""
167		},
168	})
169
170	sv, err := resolver.ResolveCloudflareToken(context.Background())
171	require.NoError(t, err)
172	assert.Equal(t, "env-token", sv.Value)
173	assert.Equal(t, domain.ACMETokenSourceEnv, sv.Source)
174}
175
176func TestPublicTLSResolverEmptyPassValueFallback(t *testing.T) {
177	// Empty string from pass (no error) should fall through to other sources
178	resolver := NewPublicTLSResolver(PublicTLSResolverConfig{
179		PassLookup: func(_ context.Context, _ string) (string, error) {
180			return "", nil // no error but empty value
181		},
182		EnvLookup: func(key string) string {
183			if key == "GORDON_CLOUDFLARE_API_TOKEN" {
184				return "env-token"
185			}
186			return ""
187		},
188	})
189
190	sv, err := resolver.ResolveCloudflareToken(context.Background())
191	require.NoError(t, err)
192	assert.Equal(t, "env-token", sv.Value)
193	assert.Equal(t, domain.ACMETokenSourceEnv, sv.Source)
194}
195
196// Ensure PublicTLSResolver implements out.SecretResolver at compile time.
197var _ out.SecretResolver = (*PublicTLSResolver)(nil)

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close