Skip to content

Commit 97d74a3

Browse files
committed
Fix proxy_exec secret masking cleanup on Windows
1 parent 81b0004 commit 97d74a3

5 files changed

Lines changed: 141 additions & 3 deletions

File tree

commands/helpers/internal/store/store.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,16 @@ func Open(dir string) (*Store, error) {
3131
sum := sha256.Sum256([]byte(pathname))
3232
keyPath := filepath.Join(dir, "runner"+hex.EncodeToString(sum[:]))
3333

34-
_ = os.MkdirAll(filepath.Dir(pathname), 0o750)
34+
_ = os.MkdirAll(filepath.Dir(pathname), 0o755)
3535
_, err := os.Stat(pathname)
3636
if err != nil {
3737
// store file doesn't exist, so re-generate key
38-
if err := os.WriteFile(keyPath, generateKey(), 0o600); err != nil {
38+
if err := os.WriteFile(keyPath, generateKey(), 0o644); err != nil {
3939
return nil, fmt.Errorf("writing key: %w", err)
4040
}
4141
}
4242

43-
f, err := os.OpenFile(pathname, os.O_APPEND|os.O_RDWR|os.O_CREATE, 0640)
43+
f, err := openFile(pathname)
4444
if err != nil {
4545
return nil, fmt.Errorf("opening store file: %w", err)
4646
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//go:build !integration
2+
3+
package store
4+
5+
import (
6+
"crypto/sha256"
7+
"encoding/hex"
8+
"os"
9+
"path/filepath"
10+
"testing"
11+
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func TestOpen(t *testing.T) {
16+
t.Run("create and reopen", func(t *testing.T) {
17+
dir := t.TempDir()
18+
19+
db, err := Open(dir)
20+
require.NoError(t, err)
21+
require.NoError(t, db.Add("test-secret"))
22+
db.Close()
23+
24+
db, err = Open(dir)
25+
require.NoError(t, err)
26+
defer db.Close()
27+
28+
items, err := db.List()
29+
require.NoError(t, err)
30+
require.Equal(t, []string{"test-secret"}, items)
31+
})
32+
33+
t.Run("recreates key when db missing", func(t *testing.T) {
34+
dir := t.TempDir()
35+
36+
db, err := Open(dir)
37+
require.NoError(t, err)
38+
require.NoError(t, db.Add("old-secret"))
39+
db.Close()
40+
41+
require.NoError(t, os.Remove(filepath.Join(dir, "masking.db")))
42+
43+
db, err = Open(dir)
44+
require.NoError(t, err)
45+
defer db.Close()
46+
47+
items, err := db.List()
48+
require.NoError(t, err)
49+
require.Empty(t, items)
50+
})
51+
52+
t.Run("fails with missing key file", func(t *testing.T) {
53+
dir := t.TempDir()
54+
55+
db, err := Open(dir)
56+
require.NoError(t, err)
57+
db.Close()
58+
59+
pathname := filepath.Join(dir, "masking.db")
60+
sum := sha256.Sum256([]byte(pathname))
61+
keyPath := filepath.Join(dir, "runner"+hex.EncodeToString(sum[:]))
62+
require.NoError(t, os.Remove(keyPath))
63+
64+
_, err = Open(dir)
65+
require.Error(t, err)
66+
})
67+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//go:build !windows
2+
3+
package store
4+
5+
import "os"
6+
7+
func openFile(pathname string) (*os.File, error) {
8+
return os.OpenFile(pathname, os.O_APPEND|os.O_RDWR|os.O_CREATE, 0666)
9+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//go:build windows
2+
3+
package store
4+
5+
import (
6+
"fmt"
7+
"os"
8+
9+
"golang.org/x/sys/windows"
10+
)
11+
12+
// openFile is like os.OpenFile, but adds FILE_SHARE_DELETE, allowing the file
13+
// to be deleted, even when open, on Windows.
14+
func openFile(pathname string) (*os.File, error) {
15+
p, err := windows.UTF16PtrFromString(pathname)
16+
if err != nil {
17+
return nil, fmt.Errorf("converting pathname to UTF16: %w", err)
18+
}
19+
20+
h, err := windows.CreateFile(
21+
p,
22+
windows.GENERIC_READ|windows.FILE_APPEND_DATA,
23+
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
24+
nil,
25+
windows.OPEN_ALWAYS,
26+
windows.FILE_ATTRIBUTE_NORMAL,
27+
0,
28+
)
29+
if err != nil {
30+
return nil, fmt.Errorf("creating file share file: %w", err)
31+
}
32+
33+
return os.NewFile(uintptr(h), pathname), nil
34+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//go:build windows && !integration
2+
3+
package store
4+
5+
import (
6+
"crypto/sha256"
7+
"encoding/hex"
8+
"os"
9+
"path/filepath"
10+
"testing"
11+
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func TestDeleteOpenFile(t *testing.T) {
16+
dir := t.TempDir()
17+
18+
pathname := filepath.Join(dir, "masking.db")
19+
sum := sha256.Sum256([]byte(pathname))
20+
keyPath := filepath.Join(dir, "runner"+hex.EncodeToString(sum[:]))
21+
22+
require.NoError(t, os.WriteFile(keyPath, nil, 0o640))
23+
db, err := Open(dir)
24+
defer db.Close()
25+
require.NoError(t, err)
26+
27+
require.NoError(t, os.Remove(pathname))
28+
}

0 commit comments

Comments
 (0)