Skip to content

Commit bf30959

Browse files
weltekialexellis
authored andcommitted
Read build secret files before sending to remote builder
For parity with local builds, read file contents from build_secrets paths in stack.yaml before sealing and sending to the remote builder. Literal secret values are no longer supported. Signed-off-by: Han Verstraete (OpenFaaS Ltd) <han@openfaas.com>
1 parent 1be251f commit bf30959

File tree

2 files changed

+74
-4
lines changed

2 files changed

+74
-4
lines changed

builder/remote_builder.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ func runRemoteBuild(builderURL *url.URL, tarPath, payloadSecretPath, builderPubl
4545

4646
var stream *sdkbuilder.BuildResultStream
4747
if len(buildSecrets) > 0 {
48-
stream, err = b.BuildWithSecretsStream(tarPath, buildSecrets)
48+
resolvedSecrets, err := readBuildSecrets(buildSecrets)
49+
if err != nil {
50+
return err
51+
}
52+
stream, err = b.BuildWithSecretsStream(tarPath, resolvedSecrets)
4953
} else {
5054
stream, err = b.BuildWithStream(tarPath)
5155
}
@@ -57,6 +61,21 @@ func runRemoteBuild(builderURL *url.URL, tarPath, payloadSecretPath, builderPubl
5761
return consumeBuildStream(stream, quietBuild, functionName, imageName)
5862
}
5963

64+
// readBuildSecrets resolves build secret values by reading file contents.
65+
// Each value in the buildSecrets map is treated as a file path. The file
66+
// is read and its contents replace the path in the returned map.
67+
func readBuildSecrets(buildSecrets map[string]string) (map[string]string, error) {
68+
resolved := make(map[string]string, len(buildSecrets))
69+
for k, v := range buildSecrets {
70+
data, err := os.ReadFile(v)
71+
if err != nil {
72+
return nil, fmt.Errorf("unable to read build secret %q from %s: %w", k, v, err)
73+
}
74+
resolved[k] = string(data)
75+
}
76+
return resolved, nil
77+
}
78+
6079
func resolveRemoteBuilderPublicKey(builderURL *url.URL, builderPublicKeyPath string) (*remoteBuilderPublicKeyResponse, error) {
6180
if builderPublicKeyPath == "" {
6281
return fetchRemoteBuilderPublicKey(builderURL)

builder/remote_builder_test.go

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func TestRunRemoteBuildWithSecrets(t *testing.T) {
109109
}
110110

111111
if err := runRemoteBuild(builderURL, tarPath, payloadSecretPath, "", map[string]string{
112-
"pip_token": "s3cr3t",
112+
"pip_token": writeTempSecret(t, "s3cr3t"),
113113
}, true, "fn", "ttl.sh/test:latest"); err != nil {
114114
t.Fatalf("runRemoteBuild returned error: %v", err)
115115
}
@@ -160,7 +160,7 @@ func TestRunRemoteBuildWithPinnedPublicKey(t *testing.T) {
160160
}
161161

162162
if err := runRemoteBuild(builderURL, tarPath, payloadSecretPath, publicKeyPath, map[string]string{
163-
"pip_token": "s3cr3t",
163+
"pip_token": writeTempSecret(t, "s3cr3t"),
164164
}, true, "fn", "ttl.sh/test:latest"); err != nil {
165165
t.Fatalf("runRemoteBuild returned error: %v", err)
166166
}
@@ -198,7 +198,7 @@ func TestRunRemoteBuildWithLiteralPublicKey(t *testing.T) {
198198
}
199199

200200
if err := runRemoteBuild(builderURL, tarPath, payloadSecretPath, string(pub), map[string]string{
201-
"pip_token": "s3cr3t",
201+
"pip_token": writeTempSecret(t, "s3cr3t"),
202202
}, true, "fn", "ttl.sh/test:latest"); err != nil {
203203
t.Fatalf("runRemoteBuild returned error: %v", err)
204204
}
@@ -224,3 +224,54 @@ func createTestTar(t *testing.T) []byte {
224224
}
225225
return buf.Bytes()
226226
}
227+
228+
func writeTempSecret(t *testing.T, content string) string {
229+
t.Helper()
230+
p := filepath.Join(t.TempDir(), "secret")
231+
if err := os.WriteFile(p, []byte(content), 0o600); err != nil {
232+
t.Fatalf("os.WriteFile returned error: %v", err)
233+
}
234+
return p
235+
}
236+
237+
func TestReadBuildSecrets(t *testing.T) {
238+
secretDir := t.TempDir()
239+
240+
npmrcPath := filepath.Join(secretDir, ".npmrc")
241+
if err := os.WriteFile(npmrcPath, []byte("//registry.npmjs.org/:_authToken=TOKEN123"), 0o600); err != nil {
242+
t.Fatal(err)
243+
}
244+
245+
netrcPath := filepath.Join(secretDir, ".netrc")
246+
if err := os.WriteFile(netrcPath, []byte("machine github.com login user password pat"), 0o600); err != nil {
247+
t.Fatal(err)
248+
}
249+
250+
secrets := map[string]string{
251+
"npmrc": npmrcPath,
252+
"netrc": netrcPath,
253+
}
254+
255+
resolved, err := readBuildSecrets(secrets)
256+
if err != nil {
257+
t.Fatalf("readBuildSecrets returned error: %v", err)
258+
}
259+
260+
if got := resolved["npmrc"]; got != "//registry.npmjs.org/:_authToken=TOKEN123" {
261+
t.Errorf("want npmrc %q, got %q", "//registry.npmjs.org/:_authToken=TOKEN123", got)
262+
}
263+
if got := resolved["netrc"]; got != "machine github.com login user password pat" {
264+
t.Errorf("want netrc %q, got %q", "machine github.com login user password pat", got)
265+
}
266+
}
267+
268+
func TestReadBuildSecrets_FileNotFound(t *testing.T) {
269+
secrets := map[string]string{
270+
"missing": "/nonexistent/path/secret.txt",
271+
}
272+
273+
_, err := readBuildSecrets(secrets)
274+
if err == nil {
275+
t.Fatal("expected error for missing file, got nil")
276+
}
277+
}

0 commit comments

Comments
 (0)