Skip to content

Commit cbc353d

Browse files
authored
Merge pull request #2925 from buildkite/fix-hook-tempdir-perms
Write hooks into new tempdir
2 parents 3867014 + 556116d commit cbc353d

File tree

2 files changed

+41
-18
lines changed

2 files changed

+41
-18
lines changed

internal/job/hook/wrapper.go

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ type WrapperOpt func(*Wrapper)
121121
type Wrapper struct {
122122
hookPath string
123123
os string
124+
tempDir string
124125
wrapperPath string
125126
beforeEnvPath string
126127
afterEnvPath string
@@ -202,19 +203,33 @@ func NewWrapper(opts ...WrapperOpt) (*Wrapper, error) {
202203
templateType = PosixShellTemplateType
203204
}
204205

205-
if wrap.beforeEnvPath, err = tempfile.NewClosed(
206-
tempfile.WithDir(hookWrapperDir),
206+
// On systems where multiple buildkite-agents are running under different
207+
// users, a shared path could be owned by a different user.
208+
// Creating a new temporary directory to hold the temporary files avoids
209+
// this issue and makes cleanup easier.
210+
tempDir, err := os.MkdirTemp(os.TempDir(), hookWrapperDir)
211+
if err != nil {
212+
return nil, fmt.Errorf("creating temporary directory for hook wrapper: %w", err)
213+
}
214+
wrap.tempDir = tempDir
215+
216+
beforeEnvPath, err := tempfile.NewClosed(
217+
tempfile.WithDir(tempDir),
207218
tempfile.WithName("hook-before-env"),
208-
); err != nil {
219+
)
220+
if err != nil {
209221
return nil, err
210222
}
223+
wrap.beforeEnvPath = beforeEnvPath
211224

212-
if wrap.afterEnvPath, err = tempfile.NewClosed(
213-
tempfile.WithDir(hookWrapperDir),
225+
afterEnvPath, err := tempfile.NewClosed(
226+
tempfile.WithDir(tempDir),
214227
tempfile.WithName("hook-after-env"),
215-
); err != nil {
228+
)
229+
if err != nil {
216230
return nil, err
217231
}
232+
wrap.afterEnvPath = afterEnvPath
218233

219234
absolutePathToHook, err := filepath.Abs(wrap.hookPath)
220235
if err != nil {
@@ -234,13 +249,16 @@ func NewWrapper(opts ...WrapperOpt) (*Wrapper, error) {
234249
PathToHook: absolutePathToHook,
235250
}
236251

237-
if wrap.wrapperPath, err = WriteHookWrapper(
252+
wrapperPath, err := WriteHookWrapper(
238253
templateType,
239254
templateInput,
255+
tempDir,
240256
scriptFileName,
241-
); err != nil {
257+
)
258+
if err != nil {
242259
return nil, err
243260
}
261+
wrap.wrapperPath = wrapperPath
244262

245263
return wrap, nil
246264
}
@@ -251,10 +269,11 @@ func NewWrapper(opts ...WrapperOpt) (*Wrapper, error) {
251269
func WriteHookWrapper(
252270
templateType TemplateType,
253271
input WrapperTemplateInput,
272+
dir string,
254273
hookWrapperName string,
255274
) (string, error) {
256275
f, err := tempfile.New(
257-
tempfile.WithDir(hookWrapperDir),
276+
tempfile.WithDir(dir),
258277
tempfile.WithName(hookWrapperName),
259278
tempfile.KeepingExtension(),
260279
tempfile.WithPerms(0o700),
@@ -291,9 +310,7 @@ func (w *Wrapper) Path() string {
291310
// Close cleans up the wrapper script and the environment files. Ignores errors, in
292311
// particular the error from os.Remove if the file doesn't exist.
293312
func (w *Wrapper) Close() {
294-
_ = os.Remove(w.wrapperPath)
295-
_ = os.Remove(w.beforeEnvPath)
296-
_ = os.Remove(w.afterEnvPath)
313+
_ = os.RemoveAll(w.tempDir)
297314
}
298315

299316
// Changes returns the changes in the environment and working dir after the hook script runs

internal/tempfile/tempfile.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ func WithName(filename string) Opts {
2626
}
2727
}
2828

29-
// WithDir sets the subdirectory of the temporary file within the system temp directory.
29+
// WithDir sets the subdirectory to contain the temporary file. If dir is
30+
// absolute, it will be used as-is, otherwise it will be taken relative to the
31+
// system temporary directory ([os.TempDir]).
3032
func WithDir(dir string) Opts {
3133
return func(tf *request) {
3234
tf.dir = dir
@@ -56,14 +58,18 @@ func New(opts ...Opts) (*os.File, error) {
5658
opt(req)
5759
}
5860

59-
tempDir := os.TempDir()
61+
dir := os.TempDir()
6062
if req.dir != "" {
61-
tempDir = filepath.Join(tempDir, req.dir)
63+
if filepath.IsAbs(req.dir) {
64+
dir = filepath.Clean(req.dir)
65+
} else {
66+
dir = filepath.Join(dir, req.dir)
67+
}
6268
}
6369

6470
// umask will make perms more reasonable
65-
if err := os.MkdirAll(tempDir, allRWX); err != nil {
66-
return nil, fmt.Errorf("failed to create temporary directory %q: %w", tempDir, err)
71+
if err := os.MkdirAll(dir, allRWX); err != nil {
72+
return nil, fmt.Errorf("failed to create temporary directory %q: %w", dir, err)
6773
}
6874

6975
tempFileName := req.filename
@@ -73,7 +79,7 @@ func New(opts ...Opts) (*os.File, error) {
7379
tempFileName = basename + "-*" + extension
7480
}
7581

76-
tempFile, err := os.CreateTemp(tempDir, tempFileName)
82+
tempFile, err := os.CreateTemp(dir, tempFileName)
7783
if err != nil {
7884
return nil, fmt.Errorf("failed to create temporary file %q: %w", req.filename, err)
7985
}

0 commit comments

Comments
 (0)