feat: globbing

Signed-off-by: jolheiser <john.olheiser@gmail.com>
main
jolheiser 2023-08-23 22:50:08 -05:00
parent 26b581b5db
commit ad992cccc8
Signed by: jolheiser
GPG Key ID: B853ADA5DA7BBF7A
9 changed files with 111 additions and 42 deletions

View File

@ -1,4 +1,3 @@
"secrets/age.txt": "secrets/*":
- age13nf8wry2lzyy0wtzq9qz0hkm2xumez074nuu0qwe8l0vsell2s2s6rgqch - age13nf8wry2lzyy0wtzq9qz0hkm2xumez074nuu0qwe8l0vsell2s2s6rgqch
"secrets/ssh.txt":
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK6qVlew2gb+lb1f/9+XgHM4oy8wRlahFpm17Ul3ln9I git-age - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK6qVlew2gb+lb1f/9+XgHM4oy8wRlahFpm17Ul3ln9I git-age

2
.gitattributes vendored
View File

@ -1,2 +1,2 @@
secrets/** filter=git-age diff=git-age secrets/* filter=git-age diff=git-age

View File

@ -50,8 +50,9 @@ func actionClean(ctx *cli.Context) error {
return err return err
} }
_, rekey := os.LookupEnv(REKEY)
sum := hasher.Sum(nil) 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")) saved, err := os.ReadFile(filepath.Join(dir, "age"))
if err != nil { if err != nil {
return err return err
@ -76,7 +77,7 @@ func actionClean(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
if string(headDecrypted) == stdin.String() { if !rekey && string(headDecrypted) == stdin.String() {
ageFile.Write(headEncrypted) ageFile.Write(headEncrypted)
os.Stdout.Write(headEncrypted) os.Stdout.Write(headEncrypted)
return nil return nil

View File

@ -12,6 +12,7 @@ import (
"filippo.io/age" "filippo.io/age"
"filippo.io/age/agessh" "filippo.io/age/agessh"
"github.com/bmatcuk/doublestar/v4"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
@ -20,6 +21,8 @@ var (
debug = false debug = false
) )
const REKEY = "GIT_AGE_REKEY"
func New() *cli.App { func New() *cli.App {
app := cli.NewApp() app := cli.NewApp()
app.Name = "git-age" app.Name = "git-age"
@ -29,6 +32,7 @@ func New() *cli.App {
Clean, Clean,
Identity, Identity,
Init, Init,
Rekey,
Smudge, Smudge,
TextConv, TextConv,
} }
@ -78,11 +82,16 @@ func ageRecipients(file string) ([]age.Recipient, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
val, ok := cfg[file] for glob, val := range cfg {
if !ok { match, err := doublestar.Match(glob, file)
return nil, fmt.Errorf("no config found for %q", 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") var ErrNoIdentities = errors.New("no identities found")

View File

@ -12,7 +12,7 @@ import (
var Identity = &cli.Command{ var Identity = &cli.Command{
Name: "identity", Name: "identity",
Aliases: []string{"i", "ident"}, Aliases: []string{"ident"},
Description: "Manage identity files", Description: "Manage identity files",
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.BoolFlag{ &cli.BoolFlag{

View File

@ -9,6 +9,7 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"github.com/bmatcuk/doublestar/v4"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
@ -53,45 +54,56 @@ func actionInit(ctx *cli.Context) error {
return err return err
} }
for file := range cfg { for glob := range cfg {
apn := filepath.Join(dir, file) files, err := doublestar.FilepathGlob(glob, doublestar.WithFilesOnly())
args := []string{"smudge", "-f", file} if err != nil {
if debug { return fmt.Errorf("bad glob %q: %w", glob, err)
args = append([]string{"-d"}, args...)
} }
if err := func() error { for _, file := range files {
content, err := os.ReadFile(apn) apn := filepath.Join(dir, file)
if err != nil { args := []string{"smudge", "-f", file}
return err
}
var buf bytes.Buffer
c := exec.Command(exe, args...)
c.Stdin = bytes.NewReader(content)
c.Stdout = &buf
if debug { if debug {
c.Stderr = os.Stderr args = append([]string{"-d"}, args...)
} }
if err := c.Run(); err != nil { if err := func() error {
if debug { content, err := os.ReadFile(apn)
fmt.Fprintf(os.Stderr, "could not smudge file: %v\n", err) 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 return nil
} }(); err != nil {
fi, err := os.Create(apn)
if err != nil {
return err 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
} }
} }

45
cmd/rekey.go 100644
View File

@ -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
}

1
go.mod
View File

@ -4,6 +4,7 @@ go 1.20
require ( require (
filippo.io/age v1.1.1 filippo.io/age v1.1.1
github.com/bmatcuk/doublestar/v4 v4.6.0
github.com/urfave/cli/v2 v2.25.7 github.com/urfave/cli/v2 v2.25.7
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
lukechampine.com/blake3 v1.2.1 lukechampine.com/blake3 v1.2.1

2
go.sum
View File

@ -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/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 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= 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 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=