mirror of
https://github.com/Mic92/sops-nix.git
synced 2025-12-26 22:24:59 +08:00
make writing templates more atomic
If the activation script is called twice for some reason, we might end up with a file potentially opened up and written twice.
This commit is contained in:
parent
49cffb88f6
commit
e7f4d7ed8b
1 changed files with 51 additions and 13 deletions
|
|
@ -198,7 +198,7 @@ func SecureSymlinkChown(targetFile string, path string, owner int, group int) er
|
|||
defer os.RemoveAll(dir)
|
||||
|
||||
// Create symlink to `targetFile` in the temp dir, before chowning it.
|
||||
var tmpSymlink = filepath.Join(dir, filepath.Base(path))
|
||||
tmpSymlink := filepath.Join(dir, filepath.Base(path))
|
||||
if err = os.Symlink(targetFile, tmpSymlink); err != nil {
|
||||
return fmt.Errorf(
|
||||
"cannot create symlink '%s' (pointing to '%s'): %w", path, targetFile, err)
|
||||
|
|
@ -1196,22 +1196,60 @@ func replaceRuntimeDir(path, rundir string) (ret string) {
|
|||
return
|
||||
}
|
||||
|
||||
func writeTemplate(targetDir string, template template, keysGID int, userMode bool) error {
|
||||
templatePath := filepath.Join(targetDir, template.Name)
|
||||
|
||||
if err := createParentDirs(targetDir, template.Name, keysGID, userMode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dir := filepath.Dir(templatePath)
|
||||
tempFile, err := os.CreateTemp(dir, "sops-*")
|
||||
tempfileRemoved := false
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create temporary file in directory %s: %w", dir, err)
|
||||
}
|
||||
defer func() {
|
||||
tempFile.Close() // noop if already closed
|
||||
|
||||
if !tempfileRemoved {
|
||||
if err := os.Remove(tempFile.Name()); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to remove temporary file %s: %s\n", tempFile.Name(),
|
||||
err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := tempFile.Write(template.value); err != nil {
|
||||
return fmt.Errorf("cannot write to temporary file %s: %w", tempFile.Name(), err)
|
||||
}
|
||||
|
||||
if err := tempFile.Chmod(template.mode); err != nil {
|
||||
return fmt.Errorf("cannot change mode of temporary file %s to %o: %w", tempFile.Name(), template.mode, err)
|
||||
}
|
||||
|
||||
if !userMode {
|
||||
if err := tempFile.Chown(template.owner, template.group); err != nil {
|
||||
return fmt.Errorf("cannot change owner/group of '%s' to %d/%d: %w", templatePath, template.owner, template.group, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := tempFile.Close(); err != nil {
|
||||
return fmt.Errorf("cannot close temporary file %s: %w", tempFile.Name(), err)
|
||||
}
|
||||
|
||||
if err := os.Rename(tempFile.Name(), templatePath); err != nil {
|
||||
return fmt.Errorf("cannot rename temporary file %s to %s: %w", tempFile.Name(), templatePath, err)
|
||||
}
|
||||
tempfileRemoved = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeTemplates(targetDir string, templates []template, keysGID int, userMode bool) error {
|
||||
for _, template := range templates {
|
||||
fp := filepath.Join(targetDir, template.Name)
|
||||
|
||||
if err := createParentDirs(targetDir, template.Name, keysGID, userMode); err != nil {
|
||||
if err := writeTemplate(targetDir, template, keysGID, userMode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.WriteFile(fp, []byte(template.value), template.mode); err != nil {
|
||||
return fmt.Errorf("cannot write %s: %w", fp, err)
|
||||
}
|
||||
if !userMode {
|
||||
if err := os.Chown(fp, template.owner, template.group); err != nil {
|
||||
return fmt.Errorf("cannot change owner/group of '%s' to %d/%d: %w", fp, template.owner, template.group, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue