github.com/Schaudge/grailbase@v0.0.0-20240223061707-44c758a471c0/security/keycrypt/file/file.go (about) 1 // Copyright 2018 GRAIL, Inc. All rights reserved. 2 // Use of this source code is governed by the Apache-2.0 3 // license that can be found in the LICENSE file. 4 5 // Package file implements a file-based keycrypt. 6 package file 7 8 import ( 9 "io/ioutil" 10 "os" 11 "path/filepath" 12 13 "github.com/Schaudge/grailbase/security/keycrypt" 14 ) 15 16 func init() { 17 keycrypt.RegisterFunc("file", func(h string) keycrypt.Keycrypt { 18 return &crypt{"/"} 19 }) 20 keycrypt.RegisterFunc("localfile", func(h string) keycrypt.Keycrypt { 21 // h is taken to be a namespace 22 return &crypt{filepath.Join(os.Getenv("HOME"), ".keycrypt", h)} 23 }) 24 } 25 26 type crypt struct{ path string } 27 28 func (c *crypt) Lookup(name string) keycrypt.Secret { 29 return fileSecret(filepath.Join(c.path, name)) 30 } 31 32 type fileSecret string 33 34 func (f fileSecret) Get() ([]byte, error) { 35 if _, err := os.Stat(string(f)); os.IsNotExist(err) { 36 return nil, nil 37 } 38 return ioutil.ReadFile(string(f)) 39 } 40 41 func (f fileSecret) Put(b []byte) error { 42 dir := filepath.Dir(string(f)) 43 os.MkdirAll(dir, 0777) // best effort 44 tmpfile, err := ioutil.TempFile(dir, "") 45 if err != nil { 46 return err 47 } 48 // Best effort because it's not vital and it doesn't work on Windows. 49 tmpfile.Chmod(0644) 50 if _, err := tmpfile.Write(b); err != nil { 51 return err 52 } 53 if err := tmpfile.Close(); err != nil { 54 return err 55 } 56 return os.Rename(tmpfile.Name(), string(f)) 57 }