From ad992cccc837787c0af4e9ff9f480ad693deac74 Mon Sep 17 00:00:00 2001 From: jolheiser Date: Wed, 23 Aug 2023 22:50:08 -0500 Subject: [PATCH] feat: globbing Signed-off-by: jolheiser --- .git-age.yaml | 3 +- .gitattributes | 2 +- cmd/clean.go | 5 ++-- cmd/cmd.go | 17 ++++++++--- cmd/identity.go | 2 +- cmd/init.go | 76 ++++++++++++++++++++++++++++--------------------- cmd/rekey.go | 45 +++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 ++ 9 files changed, 111 insertions(+), 42 deletions(-) create mode 100644 cmd/rekey.go diff --git a/.git-age.yaml b/.git-age.yaml index 3defe8c..639446c 100644 --- a/.git-age.yaml +++ b/.git-age.yaml @@ -1,4 +1,3 @@ -"secrets/age.txt": +"secrets/*": - age13nf8wry2lzyy0wtzq9qz0hkm2xumez074nuu0qwe8l0vsell2s2s6rgqch -"secrets/ssh.txt": - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK6qVlew2gb+lb1f/9+XgHM4oy8wRlahFpm17Ul3ln9I git-age diff --git a/.gitattributes b/.gitattributes index 9ac8787..21294fb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ -secrets/** filter=git-age diff=git-age +secrets/* filter=git-age diff=git-age diff --git a/cmd/clean.go b/cmd/clean.go index f001ad9..b1f3de5 100644 --- a/cmd/clean.go +++ b/cmd/clean.go @@ -50,8 +50,9 @@ func actionClean(ctx *cli.Context) error { return err } + _, rekey := os.LookupEnv(REKEY) sum := hasher.Sum(nil) - if fmt.Sprintf("%x", existing) == fmt.Sprintf("%x", sum) { + if !rekey && fmt.Sprintf("%x", existing) == fmt.Sprintf("%x", sum) { saved, err := os.ReadFile(filepath.Join(dir, "age")) if err != nil { return err @@ -76,7 +77,7 @@ func actionClean(ctx *cli.Context) error { if err != nil { return err } - if string(headDecrypted) == stdin.String() { + if !rekey && string(headDecrypted) == stdin.String() { ageFile.Write(headEncrypted) os.Stdout.Write(headEncrypted) return nil diff --git a/cmd/cmd.go b/cmd/cmd.go index b747ca3..c09ba63 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -12,6 +12,7 @@ import ( "filippo.io/age" "filippo.io/age/agessh" + "github.com/bmatcuk/doublestar/v4" "github.com/urfave/cli/v2" ) @@ -20,6 +21,8 @@ var ( debug = false ) +const REKEY = "GIT_AGE_REKEY" + func New() *cli.App { app := cli.NewApp() app.Name = "git-age" @@ -29,6 +32,7 @@ func New() *cli.App { Clean, Identity, Init, + Rekey, Smudge, TextConv, } @@ -78,11 +82,16 @@ func ageRecipients(file string) ([]age.Recipient, error) { if err != nil { return nil, err } - val, ok := cfg[file] - if !ok { - return nil, fmt.Errorf("no config found for %q", file) + for glob, val := range cfg { + match, err := doublestar.Match(glob, file) + if err != nil { + return nil, fmt.Errorf("bad glob %q: %w", glob, err) + } + if match { + return val.Recipients() + } } - return val.Recipients() + return nil, fmt.Errorf("no config found for %q", file) } var ErrNoIdentities = errors.New("no identities found") diff --git a/cmd/identity.go b/cmd/identity.go index 39937be..dac47b8 100644 --- a/cmd/identity.go +++ b/cmd/identity.go @@ -12,7 +12,7 @@ import ( var Identity = &cli.Command{ Name: "identity", - Aliases: []string{"i", "ident"}, + Aliases: []string{"ident"}, Description: "Manage identity files", Flags: []cli.Flag{ &cli.BoolFlag{ diff --git a/cmd/init.go b/cmd/init.go index 4aae21e..a1cf281 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -9,6 +9,7 @@ import ( "os/exec" "path/filepath" + "github.com/bmatcuk/doublestar/v4" "github.com/urfave/cli/v2" ) @@ -53,45 +54,56 @@ func actionInit(ctx *cli.Context) error { return err } - for file := range cfg { - apn := filepath.Join(dir, file) - args := []string{"smudge", "-f", file} - if debug { - args = append([]string{"-d"}, args...) + for glob := range cfg { + files, err := doublestar.FilepathGlob(glob, doublestar.WithFilesOnly()) + if err != nil { + return fmt.Errorf("bad glob %q: %w", glob, err) } - if err := func() error { - content, err := os.ReadFile(apn) - if err != nil { - return err - } - - var buf bytes.Buffer - c := exec.Command(exe, args...) - c.Stdin = bytes.NewReader(content) - c.Stdout = &buf + for _, file := range files { + apn := filepath.Join(dir, file) + args := []string{"smudge", "-f", file} if debug { - c.Stderr = os.Stderr + args = append([]string{"-d"}, args...) } - if err := c.Run(); err != nil { - if debug { - fmt.Fprintf(os.Stderr, "could not smudge file: %v\n", err) + if err := func() error { + content, err := os.ReadFile(apn) + if err != nil { + return err } + + var buf bytes.Buffer + c := exec.Command(exe, args...) + c.Stdin = bytes.NewReader(content) + c.Stdout = &buf + if debug { + c.Stderr = os.Stderr + } + if err := c.Run(); err != nil { + if debug { + fmt.Fprintf(os.Stderr, "could not smudge file: %v\n", err) + } + return nil + } + + if buf.String() == "" { + // Blank content, exit + return nil + } + + fi, err := os.Create(apn) + if err != nil { + return err + } + fi.Write(buf.Bytes()) + if err := fi.Close(); err != nil { + return err + } + cmd("git", "add", "--renormalize", apn) + return nil - } - - fi, err := os.Create(apn) - if err != nil { + }(); err != nil { return err } - fi.Write(buf.Bytes()) - if err := fi.Close(); err != nil { - return err - } - cmd("git", "add", "--renormalize", apn) - - return nil - }(); err != nil { - return err } } diff --git a/cmd/rekey.go b/cmd/rekey.go new file mode 100644 index 0000000..bec71f7 --- /dev/null +++ b/cmd/rekey.go @@ -0,0 +1,45 @@ +package cmd + +import ( + "errors" + "fmt" + "io/fs" + "os" + "path/filepath" + + "github.com/bmatcuk/doublestar/v4" + "github.com/urfave/cli/v2" +) + +var Rekey = &cli.Command{ + Name: "rekey", + Aliases: []string{"r"}, + Description: "Re-key secrets", + Action: actionRekey, +} + +func actionRekey(ctx *cli.Context) error { + cfg, err := LoadConfig() + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + return nil + } + return err + } + dir, err := gitBaseDir() + if err != nil { + return err + } + os.Setenv(REKEY, "1") + for glob := range cfg { + files, err := doublestar.FilepathGlob(glob, doublestar.WithFilesOnly()) + if err != nil { + return fmt.Errorf("bad glob %q: %w", glob, err) + } + for _, file := range files { + cmd("git", "add", "--renormalize", filepath.Join(dir, file)) + } + } + + return nil +} diff --git a/go.mod b/go.mod index ee578d6..01a95d6 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.20 require ( filippo.io/age v1.1.1 + github.com/bmatcuk/doublestar/v4 v4.6.0 github.com/urfave/cli/v2 v2.25.7 gopkg.in/yaml.v3 v3.0.1 lukechampine.com/blake3 v1.2.1 diff --git a/go.sum b/go.sum index 884b7c4..cd9cf09 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ filippo.io/age v1.1.1 h1:pIpO7l151hCnQ4BdyBujnGP2YlUo0uj6sAVNHGBvXHg= filippo.io/age v1.1.1/go.mod h1:l03SrzDUrBkdBx8+IILdnn2KZysqQdbEBUQ4p3sqEQE= filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +github.com/bmatcuk/doublestar/v4 v4.6.0 h1:HTuxyug8GyFbRkrffIpzNCSK4luc0TY3wzXvzIZhEXc= +github.com/bmatcuk/doublestar/v4 v4.6.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=